Javascript 如何使用async Wait包装回调?
我的函数返回一个承诺,该承诺在http服务器启动时立即解析。这是我的代码:Javascript 如何使用async Wait包装回调?,javascript,node.js,ecmascript-6,ecmascript-2017,Javascript,Node.js,Ecmascript 6,Ecmascript 2017,我的函数返回一个承诺,该承诺在http服务器启动时立即解析。这是我的代码: function start() { return new Promise((resolve, reject) { this.server = Http.createServer(app); this.server.listen(port, () => { resolve(); }); }) } 如何将start函数转换为as
function start() {
return new Promise((resolve, reject) {
this.server = Http.createServer(app);
this.server.listen(port, () => {
resolve();
});
})
}
如何将start函数转换为async/await
const doRequest = () => new Promise((resolve, reject) {
this.server = Http.createServer(app);
this.server.listen(port, () => {
resolve();
});
})
async function start() {
await doRequest()
}
像这样的东西我相信在函数声明之前包括
async
和wait
Promise构造函数。不过请注意,您实际上是在向现有模式添加代码await
将值转换为Promise
,尽管问题代码已经使用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));
与其他答案一样,创建一个
新承诺
在这种情况下可以很好地工作,但一般来说,可以阻止您多次编写相同的内容
因此,您可以这样做:(node.js v8.0.0+)
util.promisify(some_函数)
接受一个通常接受回调的函数,并返回该函数的一个新的包装版本,该版本将返回一个承诺
通过更详细的说明步骤:
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);
可以使用更高级的promisification。这是我在尝试使
http
serverlisten
功能真正实现promisification时偶然发现的。最大的问题不是解决监听回调,而是在启动时处理错误
用Promise包装并尝试捕获(正如其他答案所建议的)或尝试捕获块不会有任何效果,因为任何Node.js服务器、net
或派生的http
/https
都是EventEmitter
实例,这意味着不会引发任何错误。相反,它们作为错误
事件发出
因此,考虑到以上所有因素,promisified serverlisten
功能的正确实现如下:
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);
});
}
处理程序中的拒绝和解析调用被预先添加到侦听器堆栈的顶部,并且它们相互取消-无论谁先触发
这样可以保证listen
方法将启动服务器或抛出可捕获的错误。我创建了一个基本的util,可能不是最合适的方法,但它更具可读性
// 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;
}
这是基本概念。但是,如果您的承诺可能返回未定义的值,则函数将永远运行(但不会崩溃)。为什么要将代码转换为异步/等待模式?考虑到有问题的代码,结果将有效地向模式中添加更多的代码。我想摆脱回调。您不能仅通过使用Promise
或async/await
来“摆脱回调”。您需要重新编写Http.createServer()
的代码库,以从code@TiagoBértolo async的意思是使承诺链的行为更像同步代码。它是糖,但是非常有用的糖(对于循环,while循环,if语句,try/catch现在就可以使用承诺了).catch(…)
如果你不在承诺内调用reject()
,它将永远不会启动,看在上帝的份上,至少在这个.server.on(“error”,…)
上拒绝它是好的、干净的、简单的。util.promisify()。
// 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;
}