如何在使用$ .when时解决竞争条件

时间:2017-07-10 07:24:05

标签: javascript jquery promise

我试图在客户端初始化控件之前使用jQuerys $.when()加载一堆本地化资源:

var fooControl = (function($, kendo, _) {

    var
        initResources = function() {
            return $.when(
                window.clientResources.getAll("Messages").done(function(d) {
                    resources["Messages"] = d;
                }),
                window.clientResources.getAll("Cost").done(function(d) {
                    resources["Cost"] = d;
                })
            );
        },

        init = function(options) {
            /*... */
        }
}


//calling:
$(function() {
    fooControl.initResources().then(fooControl.init(options));
});

我想要实现的是,initResources等待资源加载并分配给它们的变量。如果数据被缓存,它们将从API端点或localStorage加载。 实际发生的是,我收到错误Cannot read property 'CostType' of undefined,表示尚未完全加载成本资源。

所以我怀疑,对window.clientResources.getAll()的调用正在得到正确解决,而不是以下.done方法,这会导致竞争条件,资源正在丢失。

如何确保整个调用堆栈(包括resources变量的赋值)已经解析,然后才调用以下init函数?

2 个答案:

答案 0 :(得分:2)

您正在立即调用init并将其 return 值作为成功回调处理程序传递,一个简单的解决方案是使用匿名方法

fooControl.initResources().then(function(){
    fooControl.init(options);
});

答案 1 :(得分:1)

您可以使用$.Deferred(),然后仅在加载资源时解决此问题。

正如Satpal所说,then需要传递匿名函数或函数引用。

var fooControl = (function($, kendo, _) {

    var initResources = function() {
        var deferred = $.Deferred();

        $.when(
            window.clientResources.getAll("Messages"),
            window.clientResources.getAll("Cost")
        ).done(function(msgData, costData) {
            resources["Messages"] = msgData;
            resources["Cost"] = costData;
            deferred.resolve();
        });

        return deferred.promise();
    },

    init = function(options) {
        /*... */
    }
}


//calling:
$(function() {
    fooControl.initResources().then(fooControl.init.bind(this, options));
});