0

我正在开发基于 SalesForce 构建的 HTML5 移动 Web 应用程序。我们大量使用 JavaScript Remoting 函数,我想知道一种方法来等待 N(多个)这些远程函数调用完成,然后触发另一个事件或函数调用。我们试图完成的用例如下:

  1. 使用 $.mobile.showPageLoadingMsg() 显示 jQuery Spinner/Loader;
  2. 调用远程函数 1、2、3、...、N。
  3. 等待远程功能 1、2、3、...、N 返回,但不要冻结浏览器。
  4. 使用 $.mobile.hidePageLoadingMsg(); 隐藏 jQuery Spinner/Loader;

    // Show a Loading Spinner while we wait for our remote requests to complete.
    $.mobile.showPageLoadingMsg();
    
    // Remote Request 1
    MyController.f1(
        function(result, event){
            if(event.type == 'exception') {
                alert('Error: ' + event.message);                     
            } else {
                // Do stuff here such as fill in a form with the results from f1
            }
        },
        {escape:true});
    
    // Remote Request 2
    MyController.f2(
        function(result, event){
            if(event.type == 'exception') {
                alert('Error: ' + event.message);                     
            } else {
                // Do stuff here such as fill in a form with the results from f2
            }
        },
        {escape:true});
    
    // ...
    
    // Remote Request N
    MyController.fN(
        function(result, event){
            if(event.type == 'exception') {
                alert('Error: ' + event.message);                     
            } else {
                // Do stuff here such as fill in a form with the results from fN
            }
        },
        {escape:true});
    
    // I want to wait until all of my requests to finish before I hide the loading spinner.
    wait_for_all(); 
    $.mobile.hidePageLoadingMsg();  
    
4

2 回答 2

2

这是我通常处理这种情况的方式:

    function doManyAsync(doneCallback) {
        // Async worker counters
        var workers = 0;

        function tickWorkers() {
            workers--;
            if ( workers === 0 ) {
                if ( doneCallback )
                    doneCallback();
            }

        }

        // Queue off first one
        doAsyncFunc1(1,2,3, tickWorkers);
        workers++;

        // Queue off second
        doAsyncFunc2(function() {
            tickWorkers();
        });
        workers++;
        
    }

在异步函数范围之外使用异步工作计数器来跟踪它们。对于每个启动的异步函数,递增计数器。当它们完成时,回调将递减,直到它们都完成并调用完成的回调。这依赖于每个函数的递增。如果存在异步函数失败的风险,那么您可以设置超时以不时检查工作人员计数,如果它超过阈值且不是 0,则根据需要失败或生成错误。

以下是您的代码的外观:

    function doManyAsync(doneCallback) {

        // Async worker counters
        var workers = 0;

        function tickWorkers() {
            workers--;
            if ( workers === 0 ) {
                if ( doneCallback )
                    doneCallback();
            }

        }

        // Remote Request 1
        MyController.f1(
            function(result, event){
                tickWorkers();
                if(event.type == 'exception') {
                    alert('Error: ' + event.message);                     
                } else {
                    // Do stuff here such as fill in a form with the results from f1
                }
            },
            {escape:true});
        workers++;

        // Remote Request 2
        MyController.f2(
            function(result, event){
                tickWorkers();
                if(event.type == 'exception') {
                    alert('Error: ' + event.message);                     
                } else {
                    // Do stuff here such as fill in a form with the results from f2
                }
            },
            {escape:true});
        workers++;

        // ...

        // Remote Request N
        MyController.fN(
            function(result, event){
                tickWorkers();
                if(event.type == 'exception') {
                    alert('Error: ' + event.message);                     
                } else {
                    // Do stuff here such as fill in a form with the results from fN
                }
            },
            {escape:true});
        workers++;

    }

    // You would then
    $.mobile.showPageLoadingMsg();
    doManyAsync(function() {
        $.mobile.hidePageLoadingMsg();
    })
于 2012-08-30T23:15:14.063 回答
0

尝试使用 jQuery whendone函数。

$.when(asyncFunc1, asyncFunc2).done(yourCallbackHere)

这样,当第一个子句中的所有操作都完成时,您的回调函数就会被调用。

您也可以将done替换为then,并且无论提供的延迟对象是已解决还是被拒绝,都会调用您的回调。

这是您可以尝试的简单示例:

// Remote Request 1
MyController.f1(
  function(result, event){
    var dfr = $.Deferred(); // New deferred object.
    if(event.type == 'exception') {
        dfr.reject(); // Error, object should be rejected.
    } else {
        // Do stuff here such as fill in a form with the results from f1
        dfr.resolve(); // Success, object is resolved.
    }
    return dfr; // Return the deferred object.
});

可以理解,您的f1函数可能不会返回与内部回调相同的结果,dfr. 如果是这样,现在这是合理的:

$when(MyController.f1).done(successCallback); // Callback only if resolved.
$when(MyController.f2).then(alwaysCallback); // Callback if resolved or rejected.
于 2012-08-30T23:20:12.013 回答