ES8 立即调用异步函数表达式
ES8 Immediately invoked async function expression
我没有看到这些构造被广泛使用,但我发现自己编写它们是为了在通常不会 return 承诺的函数中使用 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);
});
}
});
});
这是'a thing'吗?这里有我应该注意的陷阱吗?
在这种情况下使用 async / await 的内幕是什么?
Is this 'a thing'?
是的。它不时出现,例如here。它们被称为 IIAFEs :-)
如果你想把焦点放在箭头上,你也可以称它们为IIAAF。
Are there pitfalls here I should be aware of?
每当您调用 promise-returning 函数并且不 return 将结果发送到其他地方时,您自己要对 promise 负责——这意味着您必须处理来自它。所以模式通常应该看起来像
(async () => {
…
})().catch(err => {
console.error(err);
});
如果您不想让自己担心未处理的拒绝事件。
What's the lowdown on use of async
/await
in these kind of situations?
与 then
版本相比,不多。但是,您说“外部库不期望来自此回调的 return 值 ”,这可能暗示库与异步回调不兼容,所以请注意您在做什么什么时候。它还可能取决于从回调中同步抛出的异常,因此这完全取决于库在这里的期望(如果没有期望,将来是否会改变)。您不希望将来出现不兼容性,以防库开始特殊处理 promise return 值。
不过,我还是推荐第二种模式,直接将async
函数作为回调直接传递,因为它的可读性更好。如果你想避免 return 对库的承诺,创建一个包装回调的辅助函数:
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
}));
(async () => {
await func();
})();
我没有看到这些构造被广泛使用,但我发现自己编写它们是为了在通常不会 return 承诺的函数中使用 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);
});
}
});
});
这是'a thing'吗?这里有我应该注意的陷阱吗? 在这种情况下使用 async / await 的内幕是什么?
Is this 'a thing'?
是的。它不时出现,例如here。它们被称为 IIAFEs :-)
如果你想把焦点放在箭头上,你也可以称它们为IIAAF。
Are there pitfalls here I should be aware of?
每当您调用 promise-returning 函数并且不 return 将结果发送到其他地方时,您自己要对 promise 负责——这意味着您必须处理来自它。所以模式通常应该看起来像
(async () => {
…
})().catch(err => {
console.error(err);
});
如果您不想让自己担心未处理的拒绝事件。
What's the lowdown on use of
async
/await
in these kind of situations?
与 then
版本相比,不多。但是,您说“外部库不期望来自此回调的 return 值 ”,这可能暗示库与异步回调不兼容,所以请注意您在做什么什么时候。它还可能取决于从回调中同步抛出的异常,因此这完全取决于库在这里的期望(如果没有期望,将来是否会改变)。您不希望将来出现不兼容性,以防库开始特殊处理 promise return 值。
不过,我还是推荐第二种模式,直接将async
函数作为回调直接传递,因为它的可读性更好。如果你想避免 return 对库的承诺,创建一个包装回调的辅助函数:
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
}));
(async () => {
await func();
})();