我一直试图理解为什么下面的代码没有抓住throw
。如果从async
部分删除new Promise(async (resolve, ...
关键字,那么它可以正常工作,因此它与Promise执行程序是异步函数的事实有关。
(async function() {
try {
await fn();
} catch(e) {
console.log("CAUGHT fn error -->",e)
}
})();
function fn() {
return new Promise(async (resolve, reject) => {
// ...
throw new Error("<<fn error>>");
// ...
});
}
答案here,here和here重复一遍&#34;如果您在其他任何异步回调中,则必须使用reject
& #34;,但是&#34;异步&#34;他们没有提及async
函数,所以我不认为他们的解释适用于此(如果他们这样做,我不明白如何)。
如果我们使用throw
代替reject
,则上述代码可以正常运行。我想明白,从根本上,为什么throw
在这里不起作用。谢谢!
答案 0 :(得分:9)
这是Promise
constructor antipattern的异步/等待版本!
Never ever使用async function
作为Promise
执行函数(即使您可以使其工作 1 )< /子>!
[1:致电resolve
和reject
而非使用return
和throw
声明
by&#34;异步&#34;他们没有提及
async
功能,所以我不认为他们的解释适用于此
他们也可以。 无法工作的简单示例是
new Promise(async function() {
await delay(…);
throw new Error(…);
})
相当于
new Promise(function() {
return delay(…).then(function() {
throw new Error(…);
});
})
现在很清楚,throw
在异步回调中。
Promise
constructor只能抓住同步例外,而async function
永远不会抛出 - 它总是会返回一个承诺(虽然可能会被拒绝) )。并且忽略该返回值,因为承诺正在等待resolve
被调用。
答案 1 :(得分:0)
因为从Promise执行器内部与外界“通信”的唯一方法是使用resolve
和reject
函数。您可以将以下示例用作示例:
function fn() {
return new Promise(async (resolve, reject) => {
// there is no real reason to use an async executor here since there is nothing async happening
try {
throw new Error('<<fn error>>')
} catch(error) {
return reject(error);
}
});
}
例如,当您想执行具有便捷的异步功能但又需要回调的操作时。下面的示例通过使用异步fs.promises.readFile
函数和基于回调的fs.writeFile
函数读取文件来复制文件。在现实世界中,您永远不会像这样混用fs
函数,因为没有必要。但是某些库(例如手写笔和pug)使用回调,在这些情况下,我一直都使用类似的东西。
const fs = require('fs');
function copyFile(infilePath, outfilePath) {
return new Promise(async (resolve, reject) => {
try {
// the fs.promises library provides convenient async functions
const data = await fs.promises.readFile(infilePath);
// the fs library also provides methods that use callbacks
// the following line doesn't need a return statement, because there is nothing to return the value to
// but IMO it is useful to signal intent that the function has completed (especially in more complex functions)
return fs.writeFile(outfilePath, data, (error) => {
// note that if there is an error we call the reject function
// so whether an error is thrown in the promise executor, or the callback the reject function will be called
// so from the outside, copyFile appears to be a perfectly normal async function
return (error) ? reject(error) : resolve();
});
} catch(error) {
// this will only catch errors from the main body of the promise executor (ie. the fs.promises.readFile statement
// it will not catch any errors from the callback to the fs.writeFile statement
return reject(error);
// the return statement is not necessary, but IMO communicates the intent that the function is completed
}
}
}
显然每个人都说这是一种反模式,但是当我想做一些只能通过回调完成的事情之前不做异步工作时,我会一直使用它(不适用于复制人为的示例之类的文件)。我不明白为什么人们会认为它是一种反模式(使用异步诺言执行器),并且还没有看到使我相信应该接受它作为一般规则的示例。