Asynchronous 如何仅在第一个API请求完成后才发出后续API请求?
我需要调用一个API来上传照片,这个API返回照片的ID。然后,我需要获取该ID并将其用作另一个API的参数 问题是,第二个API在第一个API有机会完成(并返回ID)之前被调用。对此我们能做些什么 我用的是阿拉莫菲尔4号和斯威夫特3号 我的代码:Asynchronous 如何仅在第一个API请求完成后才发出后续API请求?,asynchronous,swift3,metadata,alamofire,image-uploading,Asynchronous,Swift3,Metadata,Alamofire,Image Uploading,我需要调用一个API来上传照片,这个API返回照片的ID。然后,我需要获取该ID并将其用作另一个API的参数 问题是,第二个API在第一个API有机会完成(并返回ID)之前被调用。对此我们能做些什么 我用的是阿拉莫菲尔4号和斯威夫特3号 我的代码: // First API - Upload file func uploadFile(url: String, image: UIImage, callback: @escaping (JSON) -> ()) { let imag
// First API - Upload file
func uploadFile(url: String, image: UIImage, callback: @escaping (JSON) -> ()) {
let imageData = UIImagePNGRepresentation(image)
let URL2 = try! URLRequest(url: url, method: .post, headers: header)
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(imageData!, withName: "photo", fileName: "picture.png", mimeType: "image/png")
}, with: URL2, encodingCompletion: { (result) in
switch result {
case .success(let upload, _, _):
upload.responseJSON
{
response in
switch response.result {
case .success(let value):
let json = JSON(value)
callback(json)
case .failure(let error):
print(error)
}
}
case .failure(let encodingError):
print(encodingError)
}
})
}
// Second API
func Post(url: String, parameters: [String:Any], callback: @escaping (JSON) -> ()) {
Alamofire.request(url, method: .post, parameters: parameters.asParameters(), encoding: ArrayEncoding(), headers: header).responseData { (response) in
switch response.result {
case .success(let value):
callback(json)
case .failure(let error):
print(error)
}
}
}
// Calling the First API
var uploadedImage: [String:String]!
uploadFile(url: baseUrl, image: image, callback: { (json) in
DispatchQueue.main.async {
uploadedImage = ["filename": json["data"]["photo"]["filename"].stringValue, "_id": json["data"]["photo"]["_id"].stringValue]
}
})
// Calling the Second API
Post(url: baseUrl, parameters: uploadedImage) { (json) in
DispatchQueue.main.async {
self.activityIndicator.stopAnimating()
}
}
为了避免您描述的竞争条件,您必须能够以某种方式序列化这两个调用。想到的解决方案要么是障碍、阻塞呼叫,要么是回调。因为您已经在使用异步(非阻塞)调用,所以我将重点讨论最后一项 我希望伪代码解决方案对您有所帮助 假设第一次呼叫总是在第二次呼叫之前执行,您可以执行以下操作:
firstCall(paramsForFirstOfTwo){
onSuccess {
secondCall(paramsForSuccess)
}
onFailure {
secondCall(paramsForFailure)
}
}
但是,如果第一次呼叫是可选的,您可以执行以下操作:
if (someCondition){
// The above example where 1->2
} else {
secondCall(paramsForNoFirstCall)
}
如果您必须在执行第二次呼叫之前执行第一次呼叫一定次数,您可以:
let n = 3; var v = 0; // assuming these are accessible from within completedCounter()
firstCall1(...){/* after running code specific to onSuccess or onFailure call c..C..() */}
firstCall2(...){/* same as previous */}
firstCall3(...){/* same as previous */}
function completedCounter(){
// v must be locked (synchronized) or accessed atomically! See:
// http://stackoverflow.com/q/30851339/3372061 (atomics)
// http://stackoverflow.com/q/24045895/3372061 (locks)
lock(v){
if (v < n)
v += 1
else
secondCall(paramsBasedOnResultsOfFirstCalls);
}
}
设n=3;var v=0;//假设这些可以从completedCounter()中访问
firstCall1(…){/*在运行特定于onSuccess或onFailure调用c..c..c..()*/}的代码之后
firstCall2(…){/*与前面的*/}
firstCall3(…){/*与前面的*/}相同
函数completedCounter(){
//必须以原子方式锁定(同步)或访问v!请参阅:
// http://stackoverflow.com/q/30851339/3372061 (原子学)
// http://stackoverflow.com/q/24045895/3372061 (锁)
锁(v){
if(v
通常,在这种情况下避免并发的方法是将对第二个API的调用放在第一个API的“成功回调”中(这意味着第一个API必须在那时完成)。@Dev iL您是对的。但在我的情况下,有时没有图像可以上传,所以我需要立即跳转到第二个API。然后,如果/或者
跳过第一个请求,或者使用一些可能会立即失败或成功的空参数调用第一个,然后仍然将调用放在回调中的第二个…@Dev iL你确定没有其他方法吗?海森堡的原理告诉我们,我们永远不能确定。。。。不过,我相当肯定这种方法会奏效……:)@戴夫:谢谢你的努力。仍然有一个问题,因为在第二个API之前有四张可选照片需要上传。我认为这种方法不适合我的工作case@user3316585我怎么会知道呢?在任何情况下,您都可以拥有一个失败/成功请求的计数器,并让每个回调调用一个方法,该方法可以增加计数器,或者如果计数器已达到目标值,则发出第二次调用。谢谢。这很有帮助