Javascript jQuery';s when.apply和包装异步函数

Javascript jQuery';s when.apply和包装异步函数,javascript,jquery,asynchronous,jquery-deferred,Javascript,Jquery,Asynchronous,Jquery Deferred,我的代码需要等待不同数量的服务器响应,并通过requireJS加载几个javascript模块 我想利用jQuery的when.apply。不幸的是,代码的.then()部分总是在我的任何回调之前执行 以下是我的代码摘要: // load module func function loadRequireJsModule(arg, callback) { require([arg], callback); } // get layer info from server func fu

我的代码需要等待不同数量的服务器响应,并通过requireJS加载几个javascript模块

我想利用jQuery的when.apply。不幸的是,代码的.then()部分总是在我的任何回调之前执行

以下是我的代码摘要:

// load module func
function loadRequireJsModule(arg, callback) {
    require([arg], callback);
}

// get layer info from server func  
function getLayerInfoFromServer(arg, callback) {
    var layerInfoListener = new DataLayer([arg]);
    layerInfoListener.addRetrievedCallback(callback);
    layerInfoListener.retrieveLayerInfo();
}

tasks.push( $.Deferred( function() {
    loadRequireJsModule( "./" + layerJSON.type, function( module ) {
        layer.controller = module;
    });
}));

for (i=0; i<layerJSON.views.length; i++) {

    layer.views[i] = {};

    // get renderer class from require.js
    tasks.push( $.Deferred( function() {

        loadRequireJsModule( "./impl/" + layerJSON.views[i].renderer, function( index ){
            return function( module ) {
                layer.views[index].renderer = new module();
            }
        }(i));
    }));

    // POST request for layerInfo
    tasks.push( $.Deferred( function() {

        getLayerInfoFromServer( {
            request: "configure",
            layer:  layerJSON.layer,
            configuration: layerJSON.views[i]
        }, function( index ){
            return function( dataLayer, layerInfo ) {
                layer.views[index].dataService = new TileService( layerInfo );
            }
        }(i));
    }));
}

$.when.apply($, tasks).then( function() {
    ...
}
//加载模块func
函数loadRequireJsModule(参数,回调){
需要([arg],回调);
}
//从服务器func获取图层信息
函数getLayerInfoFromServer(参数,回调){
var layerInfoListener=新数据层([arg]);
LayerFoliStener.addRetrievedCallback(回调);
layerInfoListener.retrieveLayerInfo();
}
tasks.push($.Deferred(function()){
loadRequireJsModule(“./”+layerJSON.type,函数(模块){
层控制器=模块;
});
}));

对于(i=0;iEdit),现在您已经公开了实际代码:

您没有正确使用
$.Deferred()

您上下文中的典型用法如下所示:

var d;
var tasks = [];
for (var i = 0; i < len; i++) {
    // create new deferred object
    d = $.Deferred();
    // put deferred into tasks object
    tasks.push(d);
    loadRequireJsModule( "./impl/" + layerJSON.views[i].renderer, function( index, deferred ){
        return function( module ) {
            layer.views[index].renderer = new module();
            // now that this operation is done, resolve our deferred
            deferred.resolve();
        }
    }(i, d));
}
$.when.apply($, tasks).done(function() {
    // code executes here when all the deferreds 
    // have had `.resolve()` called on them
});
显然,您不必使用所有三个操作
.done()
.notify()
.fail()
,或者您可以在
中指定所有操作。然后()
-出于教育目的,我将这三个操作都包含在注释中



如果您需要其他类型的异步操作的帮助,而这些异步操作还没有创建自己的promise对象,那么如果您展示和描述实际操作,我将很乐意提供帮助。延迟一开始很难处理,但就像很多事情一样,一旦它最终被接受,实际上非常简单而且非常有用。

编辑-否w您已经披露了实际代码:

您没有正确使用
$.Deferred()

您上下文中的典型用法如下所示:

var d;
var tasks = [];
for (var i = 0; i < len; i++) {
    // create new deferred object
    d = $.Deferred();
    // put deferred into tasks object
    tasks.push(d);
    loadRequireJsModule( "./impl/" + layerJSON.views[i].renderer, function( index, deferred ){
        return function( module ) {
            layer.views[index].renderer = new module();
            // now that this operation is done, resolve our deferred
            deferred.resolve();
        }
    }(i, d));
}
$.when.apply($, tasks).done(function() {
    // code executes here when all the deferreds 
    // have had `.resolve()` called on them
});
显然,您不必使用所有三个操作
.done()
.notify()
.fail()
,或者您可以在
中指定所有操作。然后()
-出于教育目的,我将这三个操作都包含在注释中



如果您需要其他类型的异步操作的帮助,而这些异步操作还没有创建自己的promise对象,那么如果您展示和描述实际操作,我将很乐意提供帮助。延迟一开始很难处理,但就像许多事情一样,一旦它最终融入,实际上非常简单而且非常有用。

有我发现了一种替代方法,用于在不使用数组的情况下处理并行承诺循环。相反,使用模式
promise=$。when(promise,anotherPromise)

e、 例如,像这样的事情

// Start with an empty resolved promise - undefined does the same thing!
var promise;

for (i = 0; i < layerJSON.views.length; i++) {

    layer.views[i] = {};

    // get renderer class from require.js
    promise = $.when(promise, loadRequireJsModule("./impl/" + layerJSON.views[i].renderer, function (index) {
            return function (module) {
                layer.views[index].renderer = new module();
            }
        }
    ));
}

// Now do something after all the promises are resolved
promise.then(function () {
    // Do the next part
});
//从一个空的已解析承诺开始-undefined做同样的事情!
var承诺;
对于(i=0;i
本例假设您更改
getLayerInfoFromServer
以返回承诺:

笔记:
  • 这种技术的缺点是,各个承诺的返回值以相反的顺序嵌套在彼此之间,因此不是很有用。如果您只需要知道它何时完成了所有任务,那就太好了

我发现了一种替代方法,可以在不使用数组的情况下处理并行承诺循环。相反,使用模式
promise=$。when(promise,anotherPromise)

e、 例如,像这样的事情

// Start with an empty resolved promise - undefined does the same thing!
var promise;

for (i = 0; i < layerJSON.views.length; i++) {

    layer.views[i] = {};

    // get renderer class from require.js
    promise = $.when(promise, loadRequireJsModule("./impl/" + layerJSON.views[i].renderer, function (index) {
            return function (module) {
                layer.views[index].renderer = new module();
            }
        }
    ));
}

// Now do something after all the promises are resolved
promise.then(function () {
    // Do the next part
});
//从一个空的已解析承诺开始-undefined做同样的事情!
var承诺;
对于(i=0;i
本例假设您更改
getLayerInfoFromServer
以返回承诺:

笔记:
  • 这种技术的缺点是,各个承诺的返回值以相反的顺序嵌套在彼此之间,因此不是很有用。如果您只需要知道它何时完成了所有任务,那就太好了

如果要使用
$,请返回延迟对象或承诺。如果
不正确使用
$。延迟()
对于异步操作而言,这根本不起作用。难怪这不起作用。这根本不是使用延迟对象的方式。我可以尝试在我的答案中添加更多内容。如果要使用
$,请返回延迟对象或承诺。
时,这不是正确使用
$。延迟()
对于异步操作而言,这是毫无疑问的。这不起作用。这根本不是使用延迟对象的方式。我可以尝试在我的答案中添加更多内容。我使用$.Deferred()创建我的延迟对象,并将我的函数作为参数传递。函数回调被调用,但现在$when.apply.then从未执行。我使用调试器查看,我的所有任务都是延迟对象。@Pondwater-当单个任务完成或失败时,您的代码正在解析或拒绝延迟对象吗?
$.when()当您传递给它的所有延迟对象都已解析时,
将调用它的
.done()
处理程序。或者,如果任何延迟对象被拒绝,它将调用它的
.fail()
处理程序。如果
,则会立即调用()