尝试为某些类构建先决条件链。由于未知的递归深度,我有一个ajax调用,每次创建一个新课程时都会运行。 DFDS
是一个存储延迟的全局数组。COURSES
是一个全局的课程数组。
var DFDS = []; //define global DFDS
var course = function( options ) {
...
var self = this;
this.p = { //prereqs object
a: [], // array for prereqs
rgx: /([A-Z]\w+[\ ])\w+/g,
parse: function() {
if (self.prereqs == '') return true;
self.prereqs.replace(this.rgx,function(m) {
//search through prereq string (self.prereqs) and run ajax for each match
var id = m.split(' ');
var dfd2 = $.Deferred();
DFDS.push(dfd2);
$.getJSON('/ajax/ajaxPrereqs.php',{subj:id[0],crs:id[1]},function(d) {
var d = d[0];
self.p.a.push(new course({
... //create new course in self.p.a[]
}));
dfd2.resolve();
});
});
}
};
...
//run parse function when created
this.p.parse();
return this;
}
我能够获得所期望的结构,并将所有正确的课程加载到所有正确的self.p.a[]
数组中。
所以要初始化顶级课程:
$.getJSON('/ajax/ajaxPrereqs.php',{subj:$('#subj').val()}, function(data) {
$.each(data,function() {
var d = this;
COURSES.push(new course({
s: d.subj,
c: d.crs,
t: d.titleshrt,
crd: d.credits,
chr: d.contacthrs,
prereqs: d.prereqs
}));
});
console.log(DFDS.length); //displays 10
$.when.apply($, DFDS).then(function() {
console.log('DFDS all done???');
console.log(DFDS.length);
$.each(DFDS,function() {console.log(this.state())})
$.each(COURSES,function() {
this.render();
})
});
});
问题:$.when.apply
在所有延迟解决之前运行。我的控制台说:
24
(10) resolved
(14) pending
我还尝试每5毫秒运行一次这个日志记录功能:
var interval = setInterval(function() {
console.log('--- intv ---');
var pending = 0;
var resolved = 0;
$.each(DFDS,function() {
switch(this.state()) {
case 'pending': pending++; break;
case 'resolved': resolved++; break;
default: console.log('NOT PENDING OR RESOLVED');
}
});
console.log(pending+' pending');
console.log(resolved+' resolved');
},5);
$.when.apply
运行之前的最后一个控制台条目是14个待处理,8个已解决。
完成后有92个ajax调用。所有92个返回良好数据(没有错误/失败)。
如何判断它在数组中的所有DFD之后运行.then()
(当$.when.apply
定义时,不仅仅是数组中的那些?)
答案 0 :(得分:1)
这是一个大致的想法。我在这里有几个目标。
$.getJSON()
处理程序替换.then()
中的完成回调,然后从.then()
处理程序返回嵌入的promise。这会自动将它们链接到父节点上,这样父节点就不会被解析,直到嵌入节点也被解析。并且,这适用于任意深度的嵌入式承诺。在摆脱全局变量的过程中,我不得不从course
构造函数中删除promises的创建,因为它无法返回promise。所以,我创建了一个course.init()
,其中创建并返回了promise。然后,我们可以在局部变量中累积promises并避免全局。
所以,这是一般的想法:
var course = function( options ) {
...
var self = this;
this.p = { //prereqs object
a: [], // array for prereqs
rgx: /([A-Z]\w+[\ ])\w+/g,
parse: function() {
var promises = [];
// check if we have any prereqs to process
if (self.prereqs !== '') {
self.prereqs.replace(this.rgx,function(m) {
//search through prereq string (self.prereqs) and run ajax for each match
var id = m.split(' ');
promises.push($.getJSON('/ajax/ajaxPrereqs.php',{subj:id[0],crs:id[1]}).then(function(d) {
var d = d[0];
var c = new course({
... //create new course in self.p.a[]
}));
self.p.a.push(c);
// chain all the new promises created by c.init() onto our master promise
// by returning a new promise from the .then() handler
return(c.init());
}));
});
}
// return a master promise that is resolve when all the sub promises
// created here are all done
return $.when.apply($, promises);
}
};
// call this to run the initial parse
// returns a single promise that is resolve when all the promises are done
this.init = function() {
return this.p.parse();
};
...
return this;
}
$.getJSON('/ajax/ajaxPrereqs.php',{subj:$('#subj').val()}, function(data) {
var promises = [];
var COURSES = [];
$.each(data,function() {
var d = this;
var c = new course({
s: d.subj,
c: d.crs,
t: d.titleshrt,
crd: d.credits,
chr: d.contacthrs,
prereqs: d.prereqs
});
COURSES.push(c);
promises.push(c.init());
});
$.when.apply($, promises).then(function() {
console.log('promises all done');
console.log(promises.length);
$.each(promises,function() {console.log(this.state())})
$.each(COURSES,function() {
this.render();
})
});
});
答案 1 :(得分:0)
这很有用。我感谢大家的评论。它帮助我意识到$.when.apply
在定义DFDS
时$.when.apply
只监视$.getJSON
中的延迟问题。
我将此函数放在课程构造函数.parse()
的{{1}}回调中。
function checkDFDS() {
var completed = 0;
$.each(DFDS,function() {
if (this.state()=='resolved') completed++;
});
if (completed == DFDS.length) {
$.each(COURSES,function() {
this.render();
})
}
}