我尝试编写返回异步函数的所有结果的函数,并执行一个回调,该回调推入一个数组并记录每个异步函数的结果。
作为服务员,在完成所有菜肴后带来所有菜肴。 我不明白如何获取应该返回的子参数。任务代码和我的工作解决方案如下:
任务:
var dishOne = function(child) {
setTimeout(function() {
child('soup');
}, 1000);
};
var dishTwo = function(child) {
setTimeout(function() {
child('dessert');
}, 1500);
};
waiter([dishOne, dishTwo], function(results) {
console.log(results); // console output = ['soup', 'dessert']
});
我的工作解决方案:
function child(arg) {
this.arr.push(arg)
}
function waiter(funcArray, doneAll) {
var result = {
arr: []
};
let i = 0;
const x = child.bind(result)
funcArray.forEach(function(f) {
f(x)
i++;
if(i == 2) {
doneAll(result.arr)
}
});
}
答案 0 :(得分:5)
问题在于这部分:
funcArray.forEach(function(f) {
f(x)
i++;
if(i == 2) {
doneAll(result.arr)
}
});
这是一个同步函数所以当你检查if(i == 2)
时,你基本上检查一下,你已经调用了所有异步函数,但它们还没有返回任何内容,所以你所知道的是,函数已被调用,但result.arr
尚未填充。
您必须将doneAll(result.arr)
表达式移动到child
回调中,然后它将由异步函数调用,因为它会返回结果。
我能想到的最简单的解决方案是将child
写为
function child(arg) {
if (this.arr.push(arg) === this.allCount) this.doneAll(this.arr);
}
并在您的waiter
函数增强结果对象
var result = {
arr: []
, allCount: funcArray.length
, doneAll: doneAll
};
这应该有效,但有一个缺点 - 结果的位置不能保持funcArray
中函数的位置,结果的位置按异步函数的持续时间排序,只需先解析第一个结果等如果这是一个问题,你必须将index传递给你的child
函数,将结果存储在结果数组中的宝贵位置,然后arr.length
的检查不起作用,因为JS数组返回长度为最高指数+ 1,因此,如果您的上一个funcArray
首先满足,它将填充最后一个索引,result.arr
的长度将等于this.allCount
,因此为了保持结果的顺序与funcArray
相同,您需要将返回结果的数量存储为另一个数字,并在每个新结果中增加该数字,并将该数字与allCount
进行比较。
或者像这样减少allCount
function child(idx, arg) {
this.arr[idx] = arg;
if (--this.allCount === 0) this.doneAll(this.arr);
}
并修改您的waiter
功能
function waiter(funcArray, doneAll) {
const result = {
arr: []
, allCount: funcArray.length
, doneAll: doneAll
};
funcArray.forEach(function(f, i) {
f(child.bind(result, i));
});
}
答案 1 :(得分:0)
为什么不Promise?
function dishOne() {
return new Promise(function(resolve, reject) {
setTimeout(function() { resolve('soup') }, 1000)
})
}
function dishTwo() {
return new Promise(function(resolve, reject) {
setTimeout(function() { resolve('dessert') }, 1500)
})
}
您的waiter
功能:
function waiter(dishes, callback) {
return Promise.all(dishes).then(callback)
}
你可以像这样使用它
waiter([dishOne(), dishTwo()], function(results) {
// Invoked when all dishes are done
console.log(results) // ['soup', dessert']
})
更容易理解。正确?