短路 Promise.allSerial(),没有异步等待
A short-circuiting Promise.allSerial(), without async-await
我需要执行一系列异步任务,以便执行一个任务 当且仅当 该系列中紧接其前的任务成功执行。我还需要收集这些任务的部分或全部结果集。所以,如果第三个任务失败了,我需要前两个任务的结果。
现在,我可以非常轻松优雅地使用 async-await 风格的 promises 来实现上述内容,甚至可以让我满意地工作,但是 不是以下非async-await版本:
// an async task that fails on an input of 200
function task(timeout) {
return new Promise((resolve, reject) => {
console.log(`Starting a ${timeout}ms task... `);
if (timeout == 200) {
console.log(`Starting a ${timeout}ms task... FAILED. timeout = ${timeout}`);
reject(`task(${timeout}): FAILED`);
} else {
setTimeout(() => {
let result = timeout * 10;
output.push(result);
console.log(`Starting a ${timeout}ms task... done. Result: ${result}`);
resolve();
}, timeout);
}
});
}
let input = [400, 300, 200, 100, 50];
let output = [];
let p = Promise.resolve(); // initialize
for (let i = 0; i < input.length; ++i) {
let timeout = input[i];
p = p
.then(() => {
return task(timeout);
})
.catch((e) => {
throw e;
});
}
p = p.finally(() => {
console.log(`Results so far: ${output.join(", ")}`);
});
输出
Starting a 400ms task...
Starting a 400ms task... done. Result: 4000
Starting a 300ms task...
Starting a 300ms task... done. Result: 3000
Starting a 200ms task...
Starting a 200ms task... FAILED. timeout = 200
Results so far: 4000, 3000
(node:1882) UnhandledPromiseRejectionWarning: task(200): FAILED
(node:1882) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3)
(node:1882) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
问题:
我正在处理 .catch()
中被拒绝的承诺,但我收到了上述警告。为什么?
平台:
节点:12.8.3
OS: Mac OSX 10.14.4
.catch((e) => {
throw e;
});
那不是处理错误...那是抛出错误!!
处理 p
上的错误,因为您真的不想处理 task
中的错误,因为这意味着被拒绝的任务之后的任务实际上 运行。显然,您不希望这样!
// an async task that fails on an input of 200
function task(timeout) {
return new Promise((resolve, reject) => {
console.log(`Starting a ${timeout}ms task... `);
if (timeout == 200) {
console.log(`Starting a ${timeout}ms task... FAILED. timeout = ${timeout}`);
reject(`task(${timeout}): FAILED`);
} else {
setTimeout(() => {
let result = timeout * 10;
output.push(result);
console.log(`Starting a ${timeout}ms task... done. Result: ${result}`);
resolve();
}, timeout);
}
});
}
let input = [400, 300, 200, 100, 50];
let output = [];
let p = Promise.resolve(); // initialize
for (let i = 0; i < input.length; ++i) {
let timeout = input[i];
p = p
.then(() => {
return task(timeout);
});
}
p = p
.catch(() => {}) // error handled!
.finally(() => {
console.log(`Results so far: ${output.join(", ")}`);
});
作为替代方案...
- 从
task
中删除output.push
并将其移动到执行任务的地方
- 简化循环
你可以做到
function task(timeout) {
return new Promise((resolve, reject) => {
console.log(`Starting a ${timeout}ms task... `);
if (timeout == 200) {
console.log(`Starting a ${timeout}ms task... FAILED. timeout = ${timeout}`);
reject(`task(${timeout}): FAILED`);
} else {
setTimeout(() => {
let result = timeout * 10;
console.log(`Starting a ${timeout}ms task... done. Result: ${result}`);
resolve(result); // resolve the result
}, timeout);
}
});
}
let input = [400, 300, 200, 100, 50];
let output = [];
// adding the result to output here vvvvvvvvvvvvvvvvvvvvvvvvv
let p = input.reduce((p, t)=>p.then(() => task(t)).then(r => output.push(r)), Promise.resolve());
p
.catch((e) => {})
.finally(() => console.log(`Results so far: ${output.join(", ")}`))
我需要执行一系列异步任务,以便执行一个任务 当且仅当 该系列中紧接其前的任务成功执行。我还需要收集这些任务的部分或全部结果集。所以,如果第三个任务失败了,我需要前两个任务的结果。
现在,我可以非常轻松优雅地使用 async-await 风格的 promises 来实现上述内容,甚至可以让我满意地工作,但是 不是以下非async-await版本:
// an async task that fails on an input of 200
function task(timeout) {
return new Promise((resolve, reject) => {
console.log(`Starting a ${timeout}ms task... `);
if (timeout == 200) {
console.log(`Starting a ${timeout}ms task... FAILED. timeout = ${timeout}`);
reject(`task(${timeout}): FAILED`);
} else {
setTimeout(() => {
let result = timeout * 10;
output.push(result);
console.log(`Starting a ${timeout}ms task... done. Result: ${result}`);
resolve();
}, timeout);
}
});
}
let input = [400, 300, 200, 100, 50];
let output = [];
let p = Promise.resolve(); // initialize
for (let i = 0; i < input.length; ++i) {
let timeout = input[i];
p = p
.then(() => {
return task(timeout);
})
.catch((e) => {
throw e;
});
}
p = p.finally(() => {
console.log(`Results so far: ${output.join(", ")}`);
});
输出
Starting a 400ms task...
Starting a 400ms task... done. Result: 4000
Starting a 300ms task...
Starting a 300ms task... done. Result: 3000
Starting a 200ms task...
Starting a 200ms task... FAILED. timeout = 200
Results so far: 4000, 3000
(node:1882) UnhandledPromiseRejectionWarning: task(200): FAILED
(node:1882) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 3)
(node:1882) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
问题:
我正在处理 .catch()
中被拒绝的承诺,但我收到了上述警告。为什么?
平台:
节点:12.8.3
OS: Mac OSX 10.14.4
.catch((e) => {
throw e;
});
那不是处理错误...那是抛出错误!!
处理 p
上的错误,因为您真的不想处理 task
中的错误,因为这意味着被拒绝的任务之后的任务实际上 运行。显然,您不希望这样!
// an async task that fails on an input of 200
function task(timeout) {
return new Promise((resolve, reject) => {
console.log(`Starting a ${timeout}ms task... `);
if (timeout == 200) {
console.log(`Starting a ${timeout}ms task... FAILED. timeout = ${timeout}`);
reject(`task(${timeout}): FAILED`);
} else {
setTimeout(() => {
let result = timeout * 10;
output.push(result);
console.log(`Starting a ${timeout}ms task... done. Result: ${result}`);
resolve();
}, timeout);
}
});
}
let input = [400, 300, 200, 100, 50];
let output = [];
let p = Promise.resolve(); // initialize
for (let i = 0; i < input.length; ++i) {
let timeout = input[i];
p = p
.then(() => {
return task(timeout);
});
}
p = p
.catch(() => {}) // error handled!
.finally(() => {
console.log(`Results so far: ${output.join(", ")}`);
});
作为替代方案...
- 从
task
中删除output.push
并将其移动到执行任务的地方 - 简化循环
你可以做到
function task(timeout) {
return new Promise((resolve, reject) => {
console.log(`Starting a ${timeout}ms task... `);
if (timeout == 200) {
console.log(`Starting a ${timeout}ms task... FAILED. timeout = ${timeout}`);
reject(`task(${timeout}): FAILED`);
} else {
setTimeout(() => {
let result = timeout * 10;
console.log(`Starting a ${timeout}ms task... done. Result: ${result}`);
resolve(result); // resolve the result
}, timeout);
}
});
}
let input = [400, 300, 200, 100, 50];
let output = [];
// adding the result to output here vvvvvvvvvvvvvvvvvvvvvvvvv
let p = input.reduce((p, t)=>p.then(() => task(t)).then(r => output.push(r)), Promise.resolve());
p
.catch((e) => {})
.finally(() => console.log(`Results so far: ${output.join(", ")}`))