如何使用异步等待包装回调?

时间:2017-10-25 13:30:24

标签: 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();
        });
    })
}

如何将启动功能转换为async / await?

5 个答案:

答案 0 :(得分:7)

在函数声明和await 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)); 构造函数。

{{1}}

答案 1 :(得分:4)

像其他答案一样创建new Promise建议在这种情况下正常工作,但作为一般规则,util.promisify可以阻止您多次编写相同的内容。

所以你可以这样做:(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)接受一个通常接受回调的函数,并返回此函数的新的包装版本,而不是返回一个promise。

有更多解释步骤:

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);

可以使用bluebird进行更高级的宣传。

答案 2 :(得分:2)

createMultiBody
我相信

这样的事情

答案 3 :(得分:2)

当我试图使http服务器listen的功能真正实现时,这是我偶然发现的。最大的问题不是要解决listening回调,而是要解决启动时的错误。

包装Promise并尝试catch(如其他答案所建议)或try-catch块不会产生任何效果,因为任何Node.js服务器,net或派生的{{1} } / httphttps实例,这意味着不会引发任何错误。而是将它们作为EventEmitter事件发出。

因此,考虑到上述所有因素,承诺的服务器error功能的正确实现如下:

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); }); } 方法将启动服务器或引发可捕获的错误。

答案 4 :(得分:0)

我创建了一个基本的实用程序,它可能不是最合适的方法,但是可以使更具可读性 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;
}

这是基本概念。但是,如果您的诺言可能返回未定义的值,则该函数将永久运行(但不会崩溃)。