提问人: 提问时间:3/27/2017 最后编辑:Alexis Tyler 更新时间:6/19/2023 访问量:141450
在新的 Promise() 构造函数中使用 async/await 是一种反模式吗?
Is it an anti-pattern to use async/await inside of a new Promise() constructor?
问:
我正在使用该函数来控制一次的最大操作数。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.
});
});
}
如您所见,我无法将函数声明为异步函数,因为我无法访问函数的第二个回调中的值。myFunction
eachLimit
答:
您有效地在 promise 构造函数执行器函数中使用了 promise,因此这是 Promise 构造函数反模式。
您的代码是主要风险的一个很好的示例:不能安全地传播所有错误。阅读原因。
此外,使用/可以使相同的陷阱更加令人惊讶。比较:async
await
let p = new Promise(resolve => {
""(); // TypeError
resolve();
});
(async () => {
await p;
})().catch(e => console.log("Caught: " + e)); // Catches it.
使用幼稚(错误)等价物:async
let p = new Promise(async resolve => {
""(); // TypeError
resolve();
});
(async () => {
await p;
})().catch(e => console.log("Caught: " + e)); // Doesn't catch it!
在浏览器的 Web 控制台中查找最后一个。
第一个之所以有效,是因为 Promise 构造函数执行器函数中的任何直接异常都会方便地拒绝新构造的 promise(但在任何异常中,您都只能靠自己)。.then
第二个不起作用,因为函数中的任何直接异常都会拒绝异步
函数本身返回的隐式承诺。async
由于 promise 构造函数执行器函数的返回值未使用,这是个坏消息!
您的代码
没有理由不能定义为: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.
});
});
}
虽然当你有的时候,为什么要使用过时的并发控制库?await
评论
return await
return new Promise
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);
}
})
}
删除 await 和 async 将解决此问题。因为你已经应用了 Promise 对象,这就足够了。
评论
axios.get(url)
await axios.get(url)
res
res.data
async
await
new Promise()
async
await
根据 @Bergi 给出的反馈,我想强调的是,我同意上面给出的答案,宁愿选择不同的方法。
但是,如果您需要在 promise 中加入异步,我会考虑使用如下内容:
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));
- 传递给构造函数的函数不是异步的,因此 linter 不会显示错误。
Promise
- 所有异步函数都可以使用 按顺序调用。
await
- 可以添加自定义错误来验证异步操作的结果
- 错误最终被很好地捕获。
但缺点是您必须记住将其放置并附加到 .try/catch
reject
评论
Promises must be handled appropriately or explicitly marked as ignored with the void operator
async
Promise
async
new Promise
相信反模式是一种反模式
异步 promise 回调中的抛出很容易被捕获。
(async () => {
try {
await new Promise (async (FULFILL, BREAK) => {
try {
throw null;
}
catch (BALL) {
BREAK (BALL);
}
});
}
catch (BALL) {
console.log ("(A) BALL CAUGHT", BALL);
throw BALL;
}
}) ().
catch (BALL => {
console.log ("(B) BALL CAUGHT", BALL);
});
或者更简单地说,
(async () => {
await new Promise (async (FULFILL, BREAK) => {
try {
throw null;
}
catch (BALL) {
BREAK (BALL);
}
});
}) ().
catch (BALL => {
console.log ("(B) BALL CAUGHT", BALL);
});
评论
await new Promise (async (FULFILL, BREAK) => {
BREAK
throw
}) ().
(resolve, reject)
(FULFILL, BREAK)
我没有通过阅读其他答案直接意识到这一点,但重要的是评估你的异步函数以将其转换为 Promise。
因此,如果您使用如下方法定义异步函数:
let f = async () => {
// ... You can use await, try/catch, throw syntax here (see answer of Vladyslav Zavalykhatko) ..
};
你把它变成一个承诺,使用:
let myPromise = f()
然后,您可以将 is 作为 Promise 进行操作,例如使用 ...Promise.all([myPromise])
当然,您可以使用以下方法将其变成单衬垫:
(async () => { code with await })()
评论