我应该如何编写递归循环以按顺序正确执行promises?我尝试过使用Promise.all(Array.map(function(){}));这不符合我的需要,因为这些步骤需要按顺序运行。我已经尝试了我已经找到here的定制承诺,但它也有问题。
承诺:
var promiseFor = (function(condition, action, value) {
var promise = new Promise(function(resolve, reject) {
if(!condition(value)) {
return;
}
return action(value).then(promiseFor.bind(null, condition, action));
});
return promise;
});
这个的问题是它似乎停止在最深的递归调用,而不是返回继续执行循环以正确完成。
例如:在PHP中有这样的代码:
function loopThrough($source) {
foreach($source as $value) {
if($value == "single") {
//do action
} else if($value == "array") {
loopThrough($value);
}
}
}
如果我通过,请说一个文件夹结构和"单个"意味着文件,它将打印所有文件。但我承诺在第一个死胡同停止使用。
编辑:添加蓝鸟,看它是否可以帮助任何事情,仍然是相同的事情。 这是当前的循环代码var runSequence = (function(sequence, params) {
return Promise.each(sequence, function(action) {
console.log(action['Rusiavimas'] + ' - ' + action['Veiksmas']);
if(params.ButtonIndex && params.ButtonIndex != action['ButtonIndex']) {
return Promise.resolve();
}
if(action['Veiksmas'].charAt(0) == '@') {
var act = action['Veiksmas'];
var actName = act.substr(0, act.indexOf(':')).trim();
var actArg = act.substr(act.indexOf(':')+1).trim();
/* This one is the code that figures out what to do and
also calls this function to execute a sub-sequence. */
return executeAction(actName, actArg, params);
} else {
sendRequest('runQuery', action['Veiksmas']);
}
});
});
我有3个序列,每个序列由5个动作组成。第一和第二序列具有下一个序列作为其第三个动作。这是我得到的结果(数字表示哪个序列):
1 - @PirmasVeiksmas
1 - @AntrasVeiksmas
1 - @Veiksmas: list_two
2 - @PirmasVeiksmas
2 - @AntrasVeiksmas
2 - @Veiksmas: list_three
3 - @PirmasVeiksmas
3 - @AntrasVeiksmas
3 - @TreciasVeiksmas
3 - @KetvirtasVeiksmas
3 - @PenktasVeiksmas
正如你所看到它进入下一个序列并继续它应该如此,但是一旦第三个序列完成,它应该恢复第二个序列并完成第一个序列。但是一旦它在递归中遇到第一个死胡同就会停止。
EDIT2:我现在拥有的Codepen示例,以及对所发生事件的直观表示:Codepen link
输出应为:
fa1
second
sa1
third
ta1
ta2
ta3
sa3
fa3
答案 0 :(得分:1)
可以使用.reduce()
代替.map()
来完成序列中的一系列操作。
以下是一个例子:
// Helper function that creates a Promise that resolves after a second
const delay = (value) => new Promise(resolve => setTimeout(() => resolve(value), 1000));
const arr = [1, 2, 3, 4, 5];
// concurrent resolution with `.map()` and `Promise.all()`
Promise.all(arr.map(delay))
.then(console.log.bind(console)); // [1, 2, 3, 4, 5] after a second.
// sequential resolution with `.reduce()`
arr.reduce((promise, current) =>
promise
.then(() => delay(current))
.then(console.log.bind(console)),
Promise.resolve());
// second wait, 1, second wait, 2...
如果我正确理解了您的要求,那么您并不需要Promise递归,它只是您按顺序运行Promise的方式。 .reduce()
可以更简单地帮助您。
缩小过程将[1,2,3,4,5]
变为:
Promise.resolve()
.then(() => delay(1))
.then(console.log.bind(console))
.then(() => delay(2))
.then(console.log.bind(console))
.then(() => delay(3))
.then(console.log.bind(console))
.then(() => delay(4))
.then(console.log.bind(console))
.then(() => delay(5))
.then(console.log.bind(console))
请注意,如果要访问所有结果,则需要做更多工作。但我会把它作为读者的练习:)
答案 1 :(得分:0)
因此,这解决了您的codepen代码的问题,因此它提供了您想要的输出。
var sequences = {
first: ['fa1', 'second', 'fa3'],
second: ['sa1', 'third', 'sa3'],
third: ['ta1', 'ta2', 'ta3']
};
var loopThrough = (function(sequence) {
return sequence.forEach(function(action) {
return doAction(action);
});
});
var doAction = (function(action) {
var promise = new Promise(function(resolve, reject) {
console.log(action);
if(action == 'second' || action == 'third') {
//recurse into sub-sequence
return loopThrough(sequences[action]);
} else {
//do something here
}
resolve();
});
return promise;
});
loopThrough(sequences.first);