繁体   English   中英

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

[英]How do i wrap a callback with async await?

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

function start() {
    return new Promise((resolve, reject) {
        this.server = Http.createServer(app);
        this.server.listen(port, () => {
            resolve();
        });
    })
}

如何将 start 函数转换为 async/await?

在函数声明之前包含asyncawait Promise构造函数。 请注意,您实际上是在向现有模式添加代码。 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));

在这种情况下,像其他答案所建议的那样创建一个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)接受一个通常接受回调的函数,并返回此函数的新包装版本,而不是返回承诺。

有更多解释的步骤:

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 可以用bluebird完成。

const doRequest = () => new Promise((resolve, reject) {
        this.server = Http.createServer(app);
        this.server.listen(port, () => {
            resolve();
        });
    })

async function start() {
 await doRequest()
}

我相信这样的事情

这是我在尝试使http服务器listen功能真正承诺时偶然发现的。 最大的问题不是解决listening回调,而是处理启动时的错误。

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

因此,考虑到以上所有因素,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方法要么启动服务器,要么抛出可捕获的错误。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM