[英]How do i wrap a callback with async await?
My function returns a promise that resolves as soon as the http server starts.我的函数返回一个承诺,该承诺在 http 服务器启动后立即解决。 This is my code:这是我的代码:
function start() {
return new Promise((resolve, reject) {
this.server = Http.createServer(app);
this.server.listen(port, () => {
resolve();
});
})
}
How do I convert the start function to async/await?如何将 start 函数转换为 async/await?
Include async
before the function declaration and await
the Promise
constructor.在函数声明之前包含async
并await
Promise
构造函数。 Though note, you would essentially be adding code to the existing pattern.请注意,您实际上是在向现有模式添加代码。 await
converts a value to a Promise
, though the code at Question already uses Promise
constructor. await
将值转换为Promise
,尽管 Question 中的代码已经使用了Promise
构造函数。
async function start() {
let promise = await new Promise((resolve, reject) => {
this.server = Http.createServer(app);
this.server.listen(port, () => {
resolve();
});
})
.catch(err => {throw err});
return promise
}
start()
.then(data => console.log(data))
.catch(err => console.error(err));
Creating a new Promise
like the other answers suggest works fine in this case, but as a general rule, util.promisify can stop you from writing the same thing many times.在这种情况下,像其他答案所建议的那样创建一个new Promise
工作正常,但作为一般规则, util.promisify可以阻止您多次编写相同的内容。
So you can do something like this instead: (node.js v8.0.0+)所以你可以做这样的事情:(node.js v8.0.0+)
const util = require('util');
async function start() {
let server = Http.createServer(app);
await util.promisify(server.listen.bind(server))(port);
}
util.promisify(some_function)
takes a function which normally accepts a callback, and returns a new, wrapped version of this function that instead returns a promise. util.promisify(some_function)
接受一个通常接受回调的函数,并返回此函数的新包装版本,而不是返回承诺。
With more explained steps:有更多解释的步骤:
let server = Http.createServer(app);
// .bind() is needed so that .listen() keeps the correct `this` context when it is called.
// If your function does not require any specific context, leave off .bind()
let listen_promise = util.promisify(server.listen.bind(server));
await listen_promise(port);
More advanced promisification can be done with bluebird .更高级的promisification 可以用bluebird完成。
const doRequest = () => new Promise((resolve, reject) {
this.server = Http.createServer(app);
this.server.listen(port, () => {
resolve();
});
})
async function start() {
await doRequest()
}
something like this I believe我相信这样的事情
This is something I've stumbled upon when while trying to make http
server listen
function truly promisified.这是我在尝试使http
服务器listen
功能真正承诺时偶然发现的。 Biggest problem is not to resolve on listening
callback, but to handle the errors on startup.最大的问题不是解决listening
回调,而是处理启动时的错误。
Wrapping in Promise and attempt to catch
(as other answers suggest) or try-catch block won't have any effect, because any Node.js server, net
or derived http
/ https
, are EventEmitter
instances, which means no errors are thrown.包装在 Promise 中并尝试catch
(如其他答案所建议的)或 try-catch 块不会产生任何效果,因为任何 Node.js 服务器、 net
或派生的http
/ https
都是EventEmitter
实例,这意味着不会引发错误。 Instead, they are emitted as the error
event.相反,它们作为error
事件发出。
So, considering all of the above, correct implementation of promisified server listen
function is as follows:因此,考虑到以上所有因素,promisified server listen
功能的正确实现如下:
const { createServer } = require('http');
const server = createServer();
const listen = async (port, host) => {
return new Promise((resolve, reject) => {
const listeners = {};
listeners.onceError = (error) => {
server.removeListener('listening', listeners.onceListening);
reject(error);
};
listeners.onceListening = () => {
server.removeListener('error', listeners.onceError);
resolve();
};
server
.prependOnceListener('error', listeners.onceError)
.prependOnceListener('listening', listeners.onceListening);
server.listen(port, host);
});
}
Reject and resolve calls inside handlers are prepended to the top of the listeners stack, and they mutually cancel each other - whoever fires first.处理程序中的拒绝和解决调用被添加到侦听器堆栈的顶部,并且它们相互抵消 - 谁先触发。
That way it's guaranteed that listen
method will either start server or throw catchable error.这样可以保证listen
方法要么启动服务器,要么抛出可捕获的错误。
I created a basic util that may not be the most proper way to do but is way more readable IMO:我创建了一个基本的实用程序,它可能不是最合适的方法,但在 IMO 上更具可读性:
// async timout util
const timeout = async ms => new Promise(res => setTimeout(res, ms));
async function start() {
let output;
this.server = Http.createServer(app);
this.server.listen(port, () => {
output = true; // or can be any data that you want to return
});
while (output === undefined) await timeout(10);
return output;
}
This is the basic concept.这是基本概念。 However be carreful if your promise may return undefined values has the function will run forever (but this will not crash).但是,如果您的承诺可能返回未定义的值,则要小心,因为该函数将永远运行(但这不会崩溃)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.