在下面的代码中,我希望从数据库中提取一些属性 - 作为特定community
成员的id。
我进行另一次API调用以获取这些社区成员的名称。
import UIKit
class ShowCommunityViewController: UIViewController {
@IBOutlet weak var communityName: UILabel!
var communityIsCalled: String?
var comIds = [String]()
var communityId: Int?
var communityPlayers = [String]()
var communityPlayerIds = [String]()
override func viewDidAppear(_ animated: Bool) {
let myUrl = URL(string: "http://www.quasisquest.uk/KeepScore/specificCommunity.php?");
var request = URLRequest(url:myUrl!);
request.httpMethod = "POST";
let postString = "id=\(comIds[communityId!])";
// print (postString)
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
DispatchQueue.main.async
{
if error != nil {
print("error=\(error)")
return
}
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
// print (json)
if let arr = json?["players"] as? [[String:String]] {
let players = arr.flatMap { $0["player_id"]!
// print(arr)
}
print ("one ",players)
self.communityPlayerIds = players
}
} catch{
print(error)
}
}
}
task.resume()
let myUrlTwo = URL(string: "http://www.quasisquest.uk/KeepScore/getPlayers.php?");
var requestTwo = URLRequest(url:myUrlTwo!);
requestTwo.httpMethod = "POST";
let postStringTwo = "player_ids=\(self.communityPlayerIds)";
print ("two ",postStringTwo)
requestTwo.httpBody = postStringTwo.data(using: String.Encoding.utf8);
let taskTwo = URLSession.shared.dataTask(with: requestTwo) { (data: Data?, response: URLResponse?, error: Error?) in
DispatchQueue.main.async
{
if error != nil {
print("error=\(error)")
return
}
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
// print (json)
if let arr = json?["player_names"] as? [[String:String]] {
let playerNames = arr.flatMap { $0["user_name"]!
// print(arr)
}
print ("three ", playerNames)
}
} catch{
print(error)
}
}
}
taskTwo.resume()
}
override func viewDidLoad() {
super.viewDidLoad()
communityName.text = communityIsCalled
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
如果您注意到打印调试命令one, two, three
的顺序。
它们实际上按two, one, three
。
由于two
在one
之前执行,因此我的帖子字符串不需要player_ids
来查找名称。
有人可以向我解释流程吗?
答案 0 :(得分:4)
首先,让我们删除所有内容,只留下代码中的3个var $ = jQuery.noConflict();
语句
print
let task = URLSession.shared.dataTask(with: request) {
print("one")
}
task.resume()
print("two")
let taskTwo = URLSession.shared.dataTask(with: requestTwo) {
print("three")
}
taskTwo.resume()
个任务以异步方式执行。当您调用URLSession
时,它会将指令发送到另一个线程并立即跳转到下一行,而不等待task.resume()
完成。与CPU的速度相比,网络请求速度极慢,因此几乎总是在task
之前打印two
。
one
和one
的顺序不确定,具体取决于服务器响应哪一个更快。
答案 1 :(得分:0)
这是因为dataTask(request:)
是异步的。这两个任务几乎立即启动,但在HTTP-Request完成时调用completionHandler
。这可能会为每个请求花费不同的时间。
答案 2 :(得分:-1)
当您使用DispatchQueue.main.async
时,您将作业添加到可以同时运行多个作业的队列中,每个作业都会在不同的时间内运行,因此其结果不一定在命令你在代码中拥有它们。
理论上,因为我不熟悉Swift的那一点:如果没有调用DispatchQueue.main.async
那么它会按顺序执行它们但它会阻塞,代码会等待网络要求在继续之前完成,并且打印报表将按顺序排列。