如何知道两个异步函数何时完成?

时间:2015-12-23 09:40:44

标签: swift cocoa-touch

function refresh1(){
    if(NOT ZOOMED IN ON LINE){
            if(document.getElementById("Line")){
                $("#Line").data("kendoChart").dataSource.read();
                $("#Line").data("kendoChart").refresh();
            }
        }
    }

当两个功能完成后,如何进行通信?我希望能够编写我的加载函数的completionHandler,以便在完成BOTH asyncFunc1和asyncFunc2时执行,然后返回someVar1和someVar2。

3 个答案:

答案 0 :(得分:3)

您可以使用计数器来了解两种方法何时完成执行。拥有一个计数器更具可扩展性,因为它允许几乎任意数量的异步方法:

func load(completionHandler:(someVar1 : SomeType, someVar2 : SomeType) -> Void){ 
    var callbacksLeft = 2
    let completionCallback = {
        print("All calls completed, let's do some work")
    }
    func checkCompleted() {
        callbacksLeft -= 1
        if callbacksLeft == 0 {
            completionCallback()
        }
    }

    asyncFunc1() { someVar1 in
        checkCompleted()
    }
    asyncFunc2() { someVar2 in
        checkCompleted()
    }
}

或者,如果可以以相同的方式调用函数,例如两者都没有params,或者有相同的参数列表,你可以通过使用一个数组来缩短代码(这也不像在第一个实现中那样,如果你添加一个新函数,你必须在两个地方更新代码) - 更新callbacksLeft值,并添加实际的函数调用):

func load(completionHandler:(someVar1 : SomeType, someVar2 : SomeType) -> Void){ 
    let funcsToCall = [asyncFunc1, asyncFunc2]
    var callbacksLeft = funcsToCall.count
    let completionCallback = {
        print("All calls completed, let's do some work")
    }

    for funcToCall in funcsToCall {
        funcToCall {
            callbacksLeft -= 1
            if callbacksLeft == 0 {
                completionCallback()
            }
        }
    }
}

即使函数没有以相同的方式调用,也可以将它们包装在闭包中:

let funcWrapper1 = { (callback: () -> Void)
    return asyncFunc1(argumentsForFuc1, callback)
}
let funcWrapper2 = { (callback: () -> Void)
    return asyncFunc2(argumentsForFunc2, callback)
}
let funcsToCall = [funcWrapper1, funcWrapper2]

答案 1 :(得分:0)

我不确定此方法的效率如何,但您可以声明两个全局变量初始化为nil,并且当每个方法完成执行时,您可以将其各自的全局变量设置为{{1} }或someVar1值,并调用第三个方法,只有当这两个全局变量都不是someVar2时才会执行。

nil

答案 2 :(得分:0)

我建议你根本不要使用全局变量。在第一个异步函数中使用完成处理程序来调用第二个异步函数。请检查我的示例代码。

enum ErrorMessage:ErrorType {
    case asyncFunc1Error
    case asyncFunc2Error


}

func asyncFunc1(completion:(result:SomeType?,error:ErrorType?) ->Void) {
    print("Do Something Func 1")
    var result:SomeType? //fill it
    //do some checks
    if true {
        completion(result: result,error: nil)
    } else {
        completion(result: nil,error: ErrorMessage.asyncFunc1Error)

    }

}
    func asyncFunc2(completion:(result:SomeType?,error:ErrorType?) ->Void) {
        print("Do Something Func 2")
        var result:SomeType? //fill it
        //do some checks
        if true {
            completion(result: result,error: nil)
        } else {
            completion(result: nil,error: ErrorMessage.asyncFunc2Error)

        }

}
 func load(completionHandler:(someVar1 : SomeType?, someVar2 : SomeType?)-> Void){
    asyncFunc1 { (result, error) -> Void in
        if let realResult1 = result {
            //we have result
            print("Result1",realResult1)
            //call second async
            asyncFunc2({ (result, error) -> Void in
                if let realResult2 = result {

                    print("Result2",realResult2)

                    // if we reach here it means async1 and async2 were successful

                    completionHandler(someVar1: realResult1, someVar2: realResult2)
                } else {
                    //async2 failed
                    completionHandler(someVar1: realResult1, someVar2: nil)

                }
            })



        } else {
            //asyncfunc1 failed
            //you can also send some error
            completionHandler(someVar1: nil, someVar2: nil)

        }

    }

}