Javascript 如何使用async Wait包装回调?

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

我的函数返回一个承诺,该承诺在http服务器启动时立即解析。这是我的代码:

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
server
listen
功能真正实现promisification时偶然发现的。最大的问题不是解决
监听
回调,而是在启动时处理错误

用Promise包装并尝试捕获(正如其他答案所建议的)或尝试捕获块不会有任何效果,因为任何Node.js服务器、
net
或派生的
http
/
https
都是
EventEmitter
实例,这意味着不会引发任何错误。相反,它们作为
错误
事件发出

因此,考虑到以上所有因素,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);
  });
}
处理程序中的拒绝和解析调用被预先添加到侦听器堆栈的顶部,并且它们相互取消-无论谁先触发


这样可以保证
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;
}