将函数数组转换为嵌套函数调用



我得到了一个长度为 N 的函数数组,其中每个函数都有一个异步调用并接受一个回调参数。函数 [x] 的回调是函数 [x+1],函数 [N-1] 没有回调。以下是我可能会得到的示例:

function func1(callback){
$.ajax({
//Ajax settings
}).done(function(){
console.log('foo1');
if(callback) callback();
});
}
function func2(callback){
$.ajax({
//Ajax settings
}).done(function(){
console.log('foo2');
if(callback) callback();
});
}
function func3(callback){
$.ajax({
//Ajax settings
}).done(function(){
console.log('foo3');
if(callback) callback();
});
}
var funcs = [func1, func2, func3];

我是否能够为示例构建以下嵌套调用,而无需仅构建字符串并调用eval((:

func1(function(){
func2(function(){
func3()
})
})
/* 
Output:
foo1
foo2
foo3
*/

编辑:它们必须嵌套,因为我需要它们同步运行。for-loops 或foreach((创建竞争条件。

创建一个新函数,该函数链接数组中的所有函数:

funcx = funcs.reduceRight((f2, f1) => x => f1(f2(x)));

然后调用此函数:

funcx(); 

当然,您也可以按步骤完成,但可能会有点令人困惑:

funcs.reduceRight((f2, f1) => x => f1(f2(x)))();

如果你想为一个空的函数数组做好准备,你可以这样做:

funcs.reduceRight((f2, f1) => x => f1(f2(x)), x => 0)();

创建承诺可以使解决方案变得简单。请按照示例进行操作。

const delay =  (v) => {
return new Promise(r => {
setTimeout(x => r(v), 10000 * Math.random())
})
}
async function  dummyAjax() {
const data = await delay(Math.random() * 10)
return data
}
async function  func1() {
return dummyAjax()
}
async function  func2() {
return dummyAjax()
}
async function  func3() {
return dummyAjax()
}
console.time("PROMISE: TOTAL_TIME")
Promise.all([func1(), func2(), func3()])
.then((responses) => {
responses.forEach(console.log)
console.timeEnd("PROMISE: TOTAL_TIME")
})

我已经创建了一系列关于所有类型的异步方法来解决问题的解决方案。请查看我的要点页面。

https://gist.github.com/deepakshrma/1a899bf49ccb77d3b5be771907b32e4c

如果所有函数都返回了 promise,那么您的解决方案就很容易了。首先,向每个函数添加一个return语句:

function func1(callback){
return $.ajax(...);
}

然后,您可以这样做:

func1()
.then(func2)
.then(func3)
.then(result => console.log('DONE!', result))
.catch(err => console.log('OH NO!', err));

如果要保留数组,则可以执行以下操作:

var funcs = [func1, func2, func3];
funcs.reduce((promise, func, i) => {
if(i === 0) return promise();
return promise.then(func);
})
.then(result => console.log('DONE!', result))
.catch(err => console.log('OH NO!', err));

最新更新