Javascript Durandal绑定期间的竞争条件-无需承诺

Javascript Durandal绑定期间的竞争条件-无需承诺,javascript,knockout.js,durandal,Javascript,Knockout.js,Durandal,杜兰达尔在页面合成/绑定方面存在明显的竞争条件 在Stackoverflow上曾经有人问过这个问题,但给出的答案(被接受)似乎掩盖了一个潜在的种族条件,我认为这将继续吸引人们 问题如下所述: 以下是相关代码: define(function (require) { var http = require('durandal/http'); return { subjectItem: function (data) { var self = this; s

杜兰达尔在页面合成/绑定方面存在明显的竞争条件

在Stackoverflow上曾经有人问过这个问题,但给出的答案(被接受)似乎掩盖了一个潜在的种族条件,我认为这将继续吸引人们

问题如下所述:

以下是相关代码:

define(function (require) {
var http = require('durandal/http');

return {
    subjectItem: function (data) {
        var self = this;
        self.Subject_ID = data.Subject_ID;
        self.Subject_Name = data.Subject_Name;
    },
    subjects: ko.observableArray([]),
    activate: function () {
        var self = this;
        http.ajaxRequest("get", "/api/values/getsubjects")
            .done(function (allData) {
                var mappedSubjects = $.map(allData, function (list) { return new self.subjectItem(list); });
                self.subjects(mappedSubjects);
            });
    }
};
});
这个问题的答案是activate函数应该返回ajax调用的结果,这是一个承诺。这将导致Durandal在继续绑定阶段之前等待ajax调用完成

这个答案的问题是没有理由等待ajax调用完成。上面的viewmodel已经包含一个空的ObservalArray,它应该成功地绑定到带有或不带任何元素的模板。如果ajax调用完成,添加到ObservalArray的新数据将添加到页面

这可以证明如下。不要在继续绑定的同时触发ajax调用,而是在绑定完成后使用setTimeout触发ajax调用。当您这样做时,竞争条件被避免,页面每次都工作

这是修改后的代码:

define(function (require) {
var http = require('durandal/http');

return {
    subjectItem: function (data) {
        var self = this;
        self.Subject_ID = data.Subject_ID;
        self.Subject_Name = data.Subject_Name;
    },
    subjects: ko.observableArray([]),
    activate: function () {
        var self = this;
        setTimeout(function () {
          http.ajaxRequest("get", "/api/values/getsubjects")
              .done(function (allData) {
                  var mappedSubjects = $.map(allData, function (list) { return new self.subjectItem(list); });
                  self.subjects(mappedSubjects);
              });
        },1500);
    }
};
});
只有当ObservalArray在页面绑定期间更新时,页面才会中断。如果setInterval在后台定期刷新一个长寿命的ObservalArray,那么这种情况随时都可能发生(似乎是随机发生的)

所以我的问题是,如果这不是Durandal中的竞争条件,为什么当ObservateArray与页面绑定同步异步更新时,我们会出现看似随机的中断,而当绑定完成后ObservateArray更新时,却没有中断

更新: 我找到了一个引发这个问题的简单方法。假设您的viewmodel中有一个observableArray可以作为“firewallList”访问(我有),这将触发问题:

function activate() {
    var counter=0;
    var timer=setInterval(function() {
        counter++;
        if(counter > 20) {
            clearInterval(timer);
            return;
        }
        firewallList.push(new Firewall({id: counter, name: 'item'+counter, description: 'description'+counter}));
    }, 10);

}

根据我如何改变区间值,我会得到不同的结果。当它是10毫秒,我最终得到一行显示在表中。如果我把它降到7毫秒,我的表中就会有一行或两行。后续对象确实会添加到ObservalArray,但从未添加到DOM。一旦触发此问题,对ObservalArray的任何操作都不会导致DOM的任何更新。

我不确定您的证据是否表明这不是Durandal的问题。我非常确定这是Durandal的问题,但通常会建议有此问题的人,问题在于他们的代码。我真的希望这里非常有学识的人能对这个问题有更多的了解。我使用的是Durandal 1.2。我想我在这里找到了我问题的答案:从字里行间看,这听起来确实像是Durandal 1.2中的种族状况,而Durandal 2.0中已经消除了这种状况。事实上,杜兰达尔人已经“修复”了这一问题,这表明这不是一个淘汰错误。