尝试定义 promise.all
Trying to define a promise.all
我试图通过创建本书练习中的 Promise.all 方法来理解 promise 的工作原理:
https://eloquentjavascript.net/11_async.html#i_Ug+Dv9Mmsw
我尝试遍历作为方法本身的参数给出的整个数组,使用 .then 进行成功的承诺,其中处理程序的主体将结果推送到我之前在循环外定义的绑定,用于拒绝的承诺,我使用 .catch 的方式是将被拒绝的值作为 "reason" 并拒绝给它一个错误的主要承诺
function Promise_all(promises) {
return new Promise((resolve, reject) => {
if(promises.length == 0) resolve(promises);
let fullArray = [];
for(let i=0; i<promises.length ; i++){
promises[i]
.then(x => fullArray.push(x))
.catch(reason => reject(new Error(reason)));
}
resolve(fullArray);
});
}
我希望函数执行以下操作:
-从"Promises"数组中选择一个promise。
-通过在其上使用 .then 方法和处理函数来解决承诺(如果成功),该处理函数仅将结果推送到 "fullArray".
-通过在其上使用 .catch 方法和一个处理函数来解决承诺(如果被拒绝),该处理函数只需调用将由 "Promise_all" 编辑的主要承诺的拒绝处理程序.
-当循环结束时,只需解析成功承诺的 "fullArray" 个承诺。
代码根本没有像我想的那样工作,使用本书的测试代码没有return预期的结果:
Promise_all([]).then(array => {
console.log("This should be []:", array);
});
function soon(val) {
return new Promise(resolve => {
setTimeout(() => resolve(val), Math.random() * 500);
});
}
Promise_all([soon(1), soon(2), soon(3)]).then(array => {
console.log("This should be [1, 2, 3]:", array);
});
Promise_all([soon(1), Promise.reject("X"), soon(3)])
.then(array => {
console.log("We should not get here");
})
.catch(error => {
if (error != "X") {
console.log("Unexpected failure:", error);
}
});
正如@Bergi 所说,代码的问题在于“.then”和“.catch”回调是异步调用的,因此,"fullArray" 甚至在"resolve()" 即使在循环之外也会被调用。为了解决这个问题,我简单地在最后完成的承诺中添加了 "resolve()",为此,我简单地添加了一个 "counter" 绑定,它的值是 "promises" 数组的长度,并且每次在承诺中调用“.then”时减 1,当此 "counter" 等于 0 时,它调用 "resolve()".
但这只解决了用承诺填充 "fullArray" 的问题,而不是这些承诺按调用顺序正确排序的问题,为了解决这个问题,我只是在数组中枚举它们循环的 "i" 绑定,最终结果是这样的:
function Promise_all(promises) {
return new Promise((resolve, reject) => {
if(promises.length == 0) resolve(promises);
let fullArray = [],
counter = promises.length;
for(let i=0; i< promises.length ; i++){
promises[i]
.then(x => {
fullArray[i] = x;
counter--;
if(counter == 0) resolve(fullArray)})
.catch(reason => reject(new Error(reason)));
}
});
}
我试图通过创建本书练习中的 Promise.all 方法来理解 promise 的工作原理: https://eloquentjavascript.net/11_async.html#i_Ug+Dv9Mmsw
我尝试遍历作为方法本身的参数给出的整个数组,使用 .then 进行成功的承诺,其中处理程序的主体将结果推送到我之前在循环外定义的绑定,用于拒绝的承诺,我使用 .catch 的方式是将被拒绝的值作为 "reason" 并拒绝给它一个错误的主要承诺
function Promise_all(promises) {
return new Promise((resolve, reject) => {
if(promises.length == 0) resolve(promises);
let fullArray = [];
for(let i=0; i<promises.length ; i++){
promises[i]
.then(x => fullArray.push(x))
.catch(reason => reject(new Error(reason)));
}
resolve(fullArray);
});
}
我希望函数执行以下操作:
-从"Promises"数组中选择一个promise。
-通过在其上使用 .then 方法和处理函数来解决承诺(如果成功),该处理函数仅将结果推送到 "fullArray".
-通过在其上使用 .catch 方法和一个处理函数来解决承诺(如果被拒绝),该处理函数只需调用将由 "Promise_all" 编辑的主要承诺的拒绝处理程序.
-当循环结束时,只需解析成功承诺的 "fullArray" 个承诺。
代码根本没有像我想的那样工作,使用本书的测试代码没有return预期的结果:
Promise_all([]).then(array => {
console.log("This should be []:", array);
});
function soon(val) {
return new Promise(resolve => {
setTimeout(() => resolve(val), Math.random() * 500);
});
}
Promise_all([soon(1), soon(2), soon(3)]).then(array => {
console.log("This should be [1, 2, 3]:", array);
});
Promise_all([soon(1), Promise.reject("X"), soon(3)])
.then(array => {
console.log("We should not get here");
})
.catch(error => {
if (error != "X") {
console.log("Unexpected failure:", error);
}
});
正如@Bergi 所说,代码的问题在于“.then”和“.catch”回调是异步调用的,因此,"fullArray" 甚至在"resolve()" 即使在循环之外也会被调用。为了解决这个问题,我简单地在最后完成的承诺中添加了 "resolve()",为此,我简单地添加了一个 "counter" 绑定,它的值是 "promises" 数组的长度,并且每次在承诺中调用“.then”时减 1,当此 "counter" 等于 0 时,它调用 "resolve()".
但这只解决了用承诺填充 "fullArray" 的问题,而不是这些承诺按调用顺序正确排序的问题,为了解决这个问题,我只是在数组中枚举它们循环的 "i" 绑定,最终结果是这样的:
function Promise_all(promises) {
return new Promise((resolve, reject) => {
if(promises.length == 0) resolve(promises);
let fullArray = [],
counter = promises.length;
for(let i=0; i< promises.length ; i++){
promises[i]
.then(x => {
fullArray[i] = x;
counter--;
if(counter == 0) resolve(fullArray)})
.catch(reason => reject(new Error(reason)));
}
});
}