说我有类似的功能:
var bigArray = [1,2,3,4,5.........n];
for(var i=0; i<bigArray.length; i++){
if(someCondition){
setTimeout(function(){
..do_stuff..
callSomeFunction();
}, someDelayTime);
}
if(someCondition){
setTimeout(function(){
..do_stuff..
callSomeFunction();
}, someDelayTime);
}
if(someCondition){
setTimeout(function(){
..do_stuff..
callSomeFunction();
}, someDelayTime);
}
.
.
.
.
.
.
.
.
if(someCondition){
setTimeout(function(){
..do_stuff..
callSomeFunction();
}, someDelayTime);
}
}
现在我想从这个函数中得到的结果是,当所有条件都执行了它们的预期任务时,它才会移动到FOR循环的下一个迭代。换句话说,如果FOR循环内的所有条件都在当前迭代中完成了它们的工作,则FOR LOOP中的i=0
应该更改为i=1
等等。
目前此代码的行为非常随机(因为我相信setTimeout
)。我怎样才能按照我的期望做这项工作?
我最近读过有关承诺的内容(对这些内容并不了解),但我不确定如何在此代码中实现它们,或者它们是否适用于这种情况......
答案 0 :(得分:2)
请试试这个:
bigArray = [1, 2, 3, 4, 5.........n];
neededStuff = 10; // Number of finished works you need below
stuffOK = neededStuff;
function mainFunction(i) {
function loopFunction(i) {
if (someCondition) {
setTimeout(function () {
// .. do_stuff..
stuffOK++;
callSomeFunction();
}, someDelayTime);
}
if (someCondition) {
setTimeout(function () {
// .. do_stuff..
stuffOK++;
callSomeFunction();
}, someDelayTime);
}
if (someCondition) {
setTimeout(function () {
// .. do_stuff..
stuffOK++;
callSomeFunction();
}, someDelayTime);
}
/*
...
*/
if(someCondition) {
setTimeout(function () {
// .. do_stuff..
stuffOK++;
callSomeFunction();
}, someDelayTime);
}
}
if (stuffOK == neededStuff) {
i++;
stuffOK = 0; // reinit counter
loopFunction(i);
}
setTimeout('mainFunction(' + i + ');', 100);
}
mainFunction(-1);
答案 1 :(得分:2)
最初的想法来自answer Nina Scholz的某些类似问题。 如果你不喜欢promises和deferred对象,这个答案是好的。其他 Kris Kowal 的Q library将是更好的选择。
function Iterator() {
var iterator = this;
this.queue = [];
this.add = function(callback, wait) {
iterator.queue.push(iterator.wait(wait));
iterator.queue.push(function() {
callback();
iterator.next();
});
};
this.wait = function(wait) {
return function() {
setTimeout(iterator.next, wait);
};
};
this.next = function() {
iterator.queue.length && iterator.queue.shift()();
};
}
var arr = [1, 2, 3, 4, 5],
counter = -1;
var iterator = new Iterator();
(function fillNextIteration() {
if (counter >= arr.length)
return;
counter++;
iterator.add(function() {
console.log('1 - counter value is ' + counter);
}, 100);
iterator.add(function() {
console.log('2 - counter value is ' + counter);
}, 100);
iterator.add(function() {
console.log('3 - counter value is ' + counter);
}, 100);
iterator.add(function() {
console.log('4 - counter value is ' + counter);
}, 100);
iterator.add(fillNextIteration, 100);
iterator.next();
})();
Iterator类有一个队列,它是数组和一些方法:
下一步强>
当你调用next()
时,如果队列中有任何回调,它将首先获取并执行该操作。当你调用Array#shift时,它会从数组中删除并返回第一项。当这个项目是一个函数时,你可以通过在它前面添加括号来调用它。这是扩展版本:
if (iterator.queue.length > 0) {
var callback = iterator.queue.shift();
callback();
}
<强>等待强>
此方法将向队列添加额外的回调,在超时后调用下一个方法。这个是为了创造预期的延迟。
添加强> 此方法调用等待所需的延迟,然后将另一个函数附加到队列,该函数将调用回调,然后调用next以使回调链运行。
<强> fillNextIteration 强>
在解释了迭代器之后,函数fillNextIteration
上还有另一个循环,它以第一次迭代的条件开始,例如:
if (someConditionIsTrue) {
iterator.add(function() {
doWhatShallBeDone;
}, delay);
}
您可以检查所有条件,然后根据需要添加回调,如图所示。
在所有条件完成后,添加fillNextIteration
作为继续循环的最后一个操作。
自我调用功能
如您所见,fillNextIteration
是自我调用的。
这有助于减少一次调用并且像这样工作:
function f(){};
f();
最后要提的是 你可以通过调用自身内部的函数来创建一个循环。如果没有延迟或停止撤销那么这将是一个僵局。所以这也是另一个循环:
(function loop() { setTimeout(loop, delay); })();
答案 2 :(得分:-1)
希望这可以通过承诺来实现
callSomeFunction1().then(function() {
callSomeFunction2();
}).then(function() {
callSomeFunction3();
})