【问题标题】:can't do http request with async and await无法使用 async 和 await 进行 http 请求
【发布时间】:2020-02-04 21:46:18
【问题描述】:

尝试在nodejs中使用asyncawait做http请求,但是出错了。有任何想法吗?谢谢

got response: 
undefined
/home/tom/learn/node/node_modules/node-rest-client/lib/node-rest-client.js:539
            callback(parsedData,res);
            ^

TypeError: callback is not a function
    at /home/tom/learn/node/node_modules/node-rest-client/lib/node-rest-client.js:539:13
    at Object.parse (/home/tom/learn/node/node_modules/node-rest-client/lib/nrc-parser-manager.js:151:3)
    at ConnectManager.handleResponse (/home/tom/learn/node/node_modules/node-rest-client/lib/node-rest-client.js:538:32)
    at ConnectManager.handleEnd (/home/tom/learn/node/node_modules/node-rest-client/lib/node-rest-client.js:531:18)
    at IncomingMessage.<anonymous> (/home/tom/learn/node/node_modules/node-rest-client/lib/node-rest-client.js:678:34)
    at emitNone (events.js:110:20)
    at IncomingMessage.emit (events.js:207:7)
    at endReadableNT (_stream_readable.js:1059:12)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)

这里是脚本的源代码

var Client = require('node-rest-client').Client;
var client = new Client();
async function test1() {
    response = await client.get("http://localhost/tmp.txt");
    console.log("got response: ");
    console.log(response.headers);
};
test1();

nodejs 版本为 v8.4.0,在 ubuntu 14.04 上。

【问题讨论】:

  • async/await 不只是神奇地使用期望回调的函数。如果client.get() 期望回调作为参数,则如果要使用它,则必须传递回调。 async/await 使用返回承诺的异步操作,它们对这些承诺进行操作。它们不会神奇地让您跳过将回调传递给为回调设计的函数。我建议阅读更多有关如何实际使用 asyncawait 的内容。
  • 一般来说,async/await 的路径是首先将所有异步操作设计为使用 Promise 和 .then() 处理程序。然后,在所有工作正常之后,您可以将返回承诺的函数声明为async,然后您可以使用await 调用这些函数,而不是使用.then() 处理程序。这里没有神奇的捷径。从承诺设计开始。
  • 谢谢。所以我们不能只以这种方式使用第三方函数,除非它是专门为 Promise 设计的?
  • 是的,没错。 async/await 使用返回承诺的异步操作,而不是使用回调的异步操作。请阅读有关它们的更多信息并研究使用它们的代码示例。
  • 谢谢@jfriend00!

标签: node.js asynchronous


【解决方案1】:

async/await 不只是神奇地使用需要回调的函数。如果 client.get() 期望回调作为参数,则如果要使用它,则必须传递回调。 async/await 使用返回承诺的异步操作,它们对这些承诺进行操作。它们不会神奇地让您跳过将回调传递给为回调设计的函数。我建议阅读更多有关如何实际使用asyncawait 的内容。

一般来说,通往async/await 的路径是首先将所有async 操作设计为使用promise 和.then() 处理程序。然后,在所有工作正常之后,您可以将一个函数声明为要在其中使用 await 的异步函数,然后在这些异步声明的函数中,您可以调用返回带有 await 承诺的函数,而不是使用 .then() 处理程序。这里没有神奇的捷径。从承诺设计开始。

这是一个简单的承诺示例:

// asynchronous function that returns a promise that resolves to
// the eventual async value
function delay(t, val) {
   return new Promise(resolve => {
       setTimeout(() => {
           resolve(val);
       }, t);
   });
}


function run() {
    return delay(100, "hello").then(data => {
        console.log(data);
        return delay(200, "goodbye").then(data => {
           console.log(data);
        });
    }).then(() => {
        console.log("all done");
    });
}

run();

而且,这里同样适用于使用async/await

// function returning a promise declared to be async
function delay(t, val) {
   return new Promise(resolve => {
       setTimeout(() => {
           resolve(val);
       }, t);
   });
}

async function run() {
    console.log(await delay(100, "hello"));
    console.log(await delay(200, "goodbye"));
    console.log("all done");
}

run();

这两个示例都产生相同的输出和相同的输出时序,因此希望您能看到从 Promise 到 async/await 的映射。

【讨论】:

  • 谢谢@jfriend00!
【解决方案2】:

await 要求其参数返回一个承诺。您收到此错误的原因是 client.get("http://localhost/tmp.txt");不返回承诺。

所以,有两种方法可以解决此问题。

  1. 显式返回一个承诺
  2. 使用其他返回承诺的库。示例:https://www.npmjs.com/package/node-rest-client-promise

【讨论】:

    【解决方案3】:
    function clientRest(args) {
       return new Promise(resolve => {
          client.post("url", args, (data,response)=> {
            resolve(data)
          })
       })
    }
    let data_image = await clientRest(args)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-08
      • 2018-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多