我没有看到这些构造使用得太多,但我发现自己编写它们是为了在通常不会返回promise的函数中使用async / await,例如
chan.consume(queue, (msg) => {
this.pendingMsgs++; // executed immediately
(async () => {
await this.handleMessage(msg);
this.pendingMsgs--;
if (cancelled && this.pendingMsgs === 0) {
await chan.close();
await this.amqpConnectionPool.release(conn);
}
})();
});
而不是
chan.consume(queue, async (msg) => { // external lib does not expect a return value from this callback
this.pendingMsgs++; // executed in promise context(?)
await this.handleMessage(msg);
this.pendingMsgs--;
if (cancelled && this.pendingMsgs === 0) {
await chan.close();
await this.amqpConnectionPool.release(conn);
}
});
或
chan.consume(queue, (msg) => {
this.pendingMsgs++; // no await - excess function decls & nesting
this.handleMessage(msg).then(() => {
this.pendingMsgs--;
if (cancelled && this.pendingMsgs === 0) {
chan.close().then(() => {
this.amqpConnectionPool.release(conn);
});
}
});
});
这是'一件事'吗?我应该注意到这里有陷阱吗? 在这种情况下,async / await的使用是什么?
答案 0 :(得分:24)
这是'是一件事吗?
是。它偶尔出现,例如, here。他们被称为IIAFE :-)
如果你想把重点放在箭头上,你也可以称它们为IIAAFs。
我应该注意哪些陷阱?
每当你调用一个承诺返回函数并且不将结果返回到其他地方时,你自己负责这个承诺 - 这意味着你必须处理它的错误。所以模式通常应该像
(async () => {
…
})().catch(err => {
console.error(err);
});
如果您不想关注未处理的拒绝事件。
在这种情况下使用
async
/await
的情况有哪些?
与then
版本相比并不多。但是,你说" 外部库不期望来自此回调的返回值"这可能暗示库与异步回调不兼容,所以要小心什么你正在做什么。它也可能依赖于从回调中同步抛出的异常,所以这一切都取决于库在这里期望的内容(如果没有期望,那么将来是否会发生变化)。如果图书馆开始特别对待承诺返回值,您不希望将来出现不兼容现象。
但是,我仍然建议直接将async
函数作为回调直接传递的第二个模式,因为它具有更好的可读性。如果您想避免向模块返回一个promise,请创建一个包装回调函数的辅助函数:
function toVoid(fn) {
return (...args) => void fn(...args);
}
function promiseToVoid(fn) {
return (...args) => void fn(...args).catch(console.error);
}
你可以这样使用:
chan.consume(queue, toVoid(async (msg) => {
… // use `await` freely
}));
答案 1 :(得分:2)
(async () => {
await func();
})();