如何仅在第一个请求完成后才发出后续 API 请求?
How to issue a subsequent API request only after the first was done?
我需要调用一个API来上传照片,这个API return是照片的ID。然后,我需要获取该 ID 并将其用作另一个 API.
的参数
问题是,第二个 API 在第一个 API 有机会完成(和 return ID)之前被调用。对此可以做些什么?
我正在使用 Alamofire 4 和 Swift 3.
我的代码:
// 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()
}
}
为了避免您描述的竞争条件,您必须能够以某种方式序列化这两个调用。想到的解决方案是障碍、阻塞调用或回调。由于您已经在使用异步 (non-blocking) 调用,因此我将重点关注最后一项。
希望伪代码解决方案对您有所帮助。
假设第 1st 调用 总是 在 2nd 之前执行,你会做类似的事情:
firstCall(paramsForFirstOfTwo){
onSuccess {
secondCall(paramsForSuccess)
}
onFailure {
secondCall(paramsForFailure)
}
}
但是,如果第 1st 调用是可选,您可以:
if (someCondition){
// The above example where 1->2
} else {
secondCall(paramsForNoFirstCall)
}
如果您必须在执行 2nd 之前执行 1st 调用一定次数,您可以:
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:
// (atomics)
// (locks)
lock(v){
if (v < n)
v += 1
else
secondCall(paramsBasedOnResultsOfFirstCalls);
}
}
我需要调用一个API来上传照片,这个API return是照片的ID。然后,我需要获取该 ID 并将其用作另一个 API.
的参数问题是,第二个 API 在第一个 API 有机会完成(和 return ID)之前被调用。对此可以做些什么?
我正在使用 Alamofire 4 和 Swift 3.
我的代码:
// 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()
}
}
为了避免您描述的竞争条件,您必须能够以某种方式序列化这两个调用。想到的解决方案是障碍、阻塞调用或回调。由于您已经在使用异步 (non-blocking) 调用,因此我将重点关注最后一项。
希望伪代码解决方案对您有所帮助。
假设第 1st 调用 总是 在 2nd 之前执行,你会做类似的事情:
firstCall(paramsForFirstOfTwo){
onSuccess {
secondCall(paramsForSuccess)
}
onFailure {
secondCall(paramsForFailure)
}
}
但是,如果第 1st 调用是可选,您可以:
if (someCondition){
// The above example where 1->2
} else {
secondCall(paramsForNoFirstCall)
}
如果您必须在执行 2nd 之前执行 1st 调用一定次数,您可以:
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:
// (atomics)
// (locks)
lock(v){
if (v < n)
v += 1
else
secondCall(paramsBasedOnResultsOfFirstCalls);
}
}