Javascript Durandal绑定期间的竞争条件-无需承诺
杜兰达尔在页面合成/绑定方面存在明显的竞争条件 在Stackoverflow上曾经有人问过这个问题,但给出的答案(被接受)似乎掩盖了一个潜在的种族条件,我认为这将继续吸引人们 问题如下所述: 以下是相关代码: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
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中已经消除了这种状况。事实上,杜兰达尔人已经“修复”了这一问题,这表明这不是一个淘汰错误。