如何"等待"回调回来?

sea*_*078 70 javascript asynchronous callback async-await ecmascript-2017

使用简单回调时,例如下面的示例:

test() {
  api.on( 'someEvent', function( response ) {
    return response;
  });
}
Run Code Online (Sandbox Code Playgroud)

如何将函数更改为使用async/await?具体来说,假设'someEvent'保证只被调用一次,我希望函数test是一个异步函数,在执行回调之前不会返回,例如:

async test() {
  return await api.on( 'someEvent' );
}
Run Code Online (Sandbox Code Playgroud)

Mad*_*iha 106

async/await不是魔术.异步函数是一个可以为你解包api.on()Promise 的函数,因此你需要返回一个Promise来实现它.像这样的东西:

function apiOn(event) {
  return new Promise(resolve => {
    api.on(event, response => resolve(response));
  });
}
Run Code Online (Sandbox Code Playgroud)

然后

async function test() {
  return await apiOn( 'someEvent' ); // await is actually optional here
                                      // you'd return a Promise either way.
}
Run Code Online (Sandbox Code Playgroud)

但这也是一个谎言,因为异步函数本身也会返回Promises,所以你不会实际获得值test(),而是一个值的Promise,你可以这样使用:

async function whatever() {
  // snip
  const response = await test();
  // use response here
  // snip
}
Run Code Online (Sandbox Code Playgroud)

  • 我以为这是魔法 (4认同)
  • 返回承诺的函数的较短版本:```const apiOn = (event) => new Promise(resolve => api.on(event, resolve));``` (3认同)

Eri*_*ikD 5

令人讨厌的是,没有一个简单的解决方案,而且包装return new Promise(...)很麻烦,但是我发现可以使用一种可行的解决方法util.promisify(实际上,它也可以进行相同的包装,看起来更好)。

function voidFunction(someArgs, callback) {
  api.onActionwhichTakesTime(someMoreArgs, (response_we_need) => {
    callback(null, response_we_need);
  });
}
Run Code Online (Sandbox Code Playgroud)

上面的函数还没有返回任何东西。我们可以把它返回Promiseresponse传入callback做:

const util = require('util');

const asyncFunction = util.promisify(voidFunction);
Run Code Online (Sandbox Code Playgroud)

现在我们可以实际awaitcallback

async function test() {
  return await asyncFunction(args);
}
Run Code Online (Sandbox Code Playgroud)

使用时的一些规则 util.promisify

  • callback必须是函数的最后一个参数是要去promisify
  • 所谓的回调必须采用以下形式 (err, res) => {...}

有趣的是,我们不需要专门写出callback实际内容。


neg*_*tek 5

异步/等待是魔法。您可以创建一个函数asPromise来处理这种情况:

function asPromise(context, callbackFunction, ...args) {
    return new Promise((resolve, reject) => {
        args.push((err, data) => {
            if (err) {
                reject(err);
            } else {
                resolve(data);
            }
        });
        if (context) {
            callbackFunction.call(context, ...args);
        } else {
            callbackFunction(...args);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

然后在需要时使用它:

async test() {
    return await this.asPromise(this, api.on, 'someEvent');
}
Run Code Online (Sandbox Code Playgroud)

args 的数量是可变的。


小智 5

const getprice = async () => {
return await new Promise((resolve, reject) => {
    binance.prices('NEOUSDT', (error, ticker) => {
        if (error) {
            reject(error)
        } else {
            resolve(ticker);
        }
    });
})}

router.get('/binanceapi/price', async function (req, res, next) {
res.send(await binanceAPI.getprice());});
Run Code Online (Sandbox Code Playgroud)