Javascript 在新的 Promise() 构造函数中使用 async/await 是一种反模式吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43036229/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it an anti-pattern to use async/await inside of a new Promise() constructor?
提问by
I'm using the async.eachLimitfunction to control the maximum number of operations at a time.
我正在使用该async.eachLimit函数来控制一次最大操作数。
const { eachLimit } = require("async");
function myFunction() {
return new Promise(async (resolve, reject) => {
eachLimit((await getAsyncArray), 500, (item, callback) => {
// do other things that use native promises.
}, (error) => {
if (error) return reject(error);
// resolve here passing the next value.
});
});
}
As you can see, I can't declare the myFunctionfunction as async because I don't have access to the value inside the second callback of the eachLimitfunction.
如您所见,我无法将该myFunction函数声明为异步函数,因为我无法访问该eachLimit函数的第二个回调中的值。
采纳答案by jib
You're effectively using promises inside the promise constructor executor function, so this the Promise constructor anti-pattern.
您在Promise 构造函数 executor 函数中有效地使用了Promise,因此这是Promise 构造函数 anti-pattern。
Your code is a good example of the main risk: not propagating all errors safely. Read why there.
您的代码是主要风险的一个很好的例子:没有安全地传播所有错误。阅读为什么有。
In addition, the use of async/awaitcan make the same traps even more surprising. Compare:
此外,使用async/await可以使相同的陷阱更加令人惊讶。相比:
let p = new Promise(resolve => {
""(); // TypeError
resolve();
});
(async () => {
await p;
})().catch(e => console.log("Caught: " + e)); // Catches it.
with a naive (wrong) asyncequivalent:
有一个天真的(错误)async等价物:
let p = new Promise(async resolve => {
""(); // TypeError
resolve();
});
(async () => {
await p;
})().catch(e => console.log("Caught: " + e)); // Doesn't catch it!
Look in your browser's web console for the last one.
在浏览器的 Web 控制台中查看最后一个。
The first one works because any immediateexception in a Promise constructor executor function conveniently rejects the newly constructed promise (but inside any .thenyou're on your own).
第一个有效,因为Promise 构造函数 executor 函数中的任何直接异常都方便地拒绝了新构造的 Promise(但在任何.then你自己的内部)。
The second one doesn't work because any immediate exception in an asyncfunction rejects the implicit promise returned by the asyncfunction itself.
第二个不起作用,因为async函数中的任何直接异常都会拒绝函数本身返回async的隐式承诺。
Since the return value of a promise constructor executor function is unused, that's bad news!
由于 promise 构造函数执行器函数的返回值未使用,这是个坏消息!
Your code
你的代码
There's no reason you can't define myFunctionas async:
没有理由你不能定义myFunction为async:
async function myFunction() {
let array = await getAsyncArray();
return new Promise((resolve, reject) => {
eachLimit(array, 500, (item, callback) => {
// do other things that use native promises.
}, error => {
if (error) return reject(error);
// resolve here passing the next value.
});
});
}
Though why use outdated concurrency control libraries when you have await?
但是为什么要使用过时的并发控制库await呢?
回答by Alain
static getPosts(){
return new Promise( (resolve, reject) =>{
try {
const res = axios.get(url);
const data = res.data;
resolve(
data.map(post => ({
...post,
createdAt: new Date(post.createdAt)
}))
)
} catch (err) {
reject(err);
}
})
}
remove await and async will solve this issue. because you have applied Promise object, that's enough.
删除 await 和 async 将解决此问题。因为你已经应用了 Promise 对象,这就足够了。
回答by Vladyslav Zavalykhatko
I agree with the answers given above and still, sometimes it's neater to have async inside your promise, especially if you want to chain several operations returning promises and avoid the then().then()hell. I would consider using something like this in that situation:
我同意上面给出的答案,但有时在你的承诺中使用异步会更简洁,特别是如果你想链接几个返回承诺的操作并避免then().then()地狱。我会考虑在那种情况下使用这样的东西:
const operation1 = Promise.resolve(5)
const operation2 = Promise.resolve(15)
const publishResult = () => Promise.reject(`Can't publish`)
let p = new Promise((resolve, reject) => {
(async () => {
try {
const op1 = await operation1;
const op2 = await operation2;
if (op2 == null) {
throw new Error('Validation error');
}
const res = op1 + op2;
const result = await publishResult(res);
resolve(result)
} catch (err) {
reject(err)
}
})()
});
(async () => {
await p;
})().catch(e => console.log("Caught: " + e));
- The function passed to
Promiseconstructor is not async, so linters don't show errors. - All of the async functions can be called in sequential order using
await. - Custom errors can be added to validate the results of async operations
- The error is caught nicely eventually.
- 传递给
Promise构造函数的函数不是异步的,因此 linter 不会显示错误。 - 所有异步函数都可以使用
await. - 可以添加自定义错误来验证异步操作的结果
- 错误最终被很好地捕获。
A drawback though is that you have to remember putting try/catchand attaching it to reject.
但是有一个缺点是您必须记住try/catch将其放置并附加到reject.

