【问题标题】:Returning an object from a callback using async/await使用 async/await 从回调中返回对象
【发布时间】:2024-04-23 04:50:02
【问题描述】:

我无法用this question 的答案解决这个问题,因为代码存在差异。

我想从回调中返回一个对象。当我运行以下代码时,body 对象的日志看起来符合预期。它似乎是正确的 JSON 对象,其中包含我想要从服务器获得的响应:名称、电子邮件、网站等。

result 对象似乎包含有关请求本身而不是响应对象的信息。

如何返回body 对象,以便我可以从result 变量访问它?

const request = require('request'); // npm i request -s

module.exports = async config => {
  ...

  const result = await request.get( url, options,
    ( error, response, body, ) => {
      console.log( 'body', body, ); // I want the other log to look like this log.
      return body;
    }
  );

  console.log( 'result', result, ); // I want this log to look like the above log.
  // In other words, I want the below line to be the name, email, website JSON object
  // contained in the body
  return result;
}

这就是我想要的result

console.log('body', body, );
body {
  "name": "foo",
  "email": "foo@example.com",
  "website": "www.example.com",
  ...
}

这是我实际从result 得到的。

console.log('结果', 结果, );
result Request {
  _events: [Object: null prototype] {
    error: [Function: bound ],
    complete: [Function: bound ],
    pipe: [Function]
  },
  _eventsCount: 3,
  _maxListeners: undefined,
  uri: Url {
    protocol: 'https:',
    slashes: true,
    auth: null,
    host: 'api.example.com',
    port: 443,
    hostname: 'api.example.com',
    hash: null,
  },
  callback: [Function],
  method: 'GET',
  readable: true,
  writable: true,
  explicitMethod: true,
  _qs: Querystring {
    request: [Circular],
    lib: { formats: [Object], parse: [Function], stringify: [Function] },
    useQuerystring: undefined,
    parseOptions: {},
    stringifyOptions: {}
  },
  _auth: Auth {
    request: [Circular],

【问题讨论】:

  • request.get() 不返回承诺,因此 await 对它没有任何用处。如果我每次回答这个问题时都有五分钱,我会有很多五分钱。 await 没有魔法。它所做的只是等待一个承诺。如果你不给它一个承诺,它什么也做不了。

标签: javascript node.js asynchronous callback async-await


【解决方案1】:

使用Promise:

const result = await new Promise((resolve) => {
  request.get(url, options, (error, response, body) => {
      console.log( 'body', body );
      resolve(body);
    });
});

编辑:

或者你可以安装https://github.com/request/request-promise

【讨论】:

  • 仅供参考,request 模块位于 maintenance mode 中,将不再获得新功能。真的不建议用它编写新代码。
  • @jfriend00 维护模式并不意味着不受支持。这只是意味着开发人员认为不需要添加任何其他内容。如果它有你需要的一切,在新代码中使用它是非常好的。
  • @Tarazed - 好吧,这是死胡同的代码。如果 nodejs 实现了一种新的流类型,它与 Promise 一起使用更友好,你认为request 模块会支持这种新类型的流吗?我不。它正在修复错误,仅此而已。如果您正在编写新代码,最好选择一个正在积极开发的替代方案。现在,如果您现在使用request() 库,世界不会在明天结束,但我认为这不是新代码最明智的选择。也值得理解为什么它被置于维护模式。
【解决方案2】:

request.get() 不返回承诺,因此 await 对它没有任何用处。如果我每次回答这个问题时都有五分钱,我会有很多五分钱。 await 没有魔法。它所做的只是等待一个承诺。如果你不给它一个承诺,它什么也做不了。

您可能不知道,request 模块及其衍生模块在maintenance mode 中(没有新功能,只有错误修复)。您可以使用request-promise 模块然后摆脱回调,或者您可以切换到正在积极开发的更新模块,例如got 模块。这是我的建议:

const got = require('got');

module.exports = async config => {
  ...

  const result = await got(url, options);

  console.log( 'result', result ); // I want this log to look like the above log.
  // In other words, I want the below line to be the name, email, website JSON object
  // contained in the body
  return result;
}

而且,我希望你意识到所有async 函数都返回一个promise,所以这个函数的调用者必须在返回的promise 上使用await.then() 才能得到promise 的结果.


如果您想继续使用 request 库,您可以使用 request-promise 来获取该库的已承诺版本:

const rp = require('request-promise');

module.exports = async config => {
  ...

  const result = await rp(url, options);

  console.log( 'result', result ); // I want this log to look like the above log.
  // In other words, I want the below line to be the name, email, website JSON object
  // contained in the body
  return result;
}

【讨论】:

  • 非常感谢。 +1。您提供的有关 async 以及 requestgot 模块的附加上下文一针见血。
最近更新 更多