【问题标题】:How to await and return the result of a http.request(), so that multiple requests run serially?如何等待并返回 http.request() 的结果,以便多个请求串行运行?
【发布时间】:2021-03-27 01:26:27
【问题描述】:

假设有一个函数doRequest(options),它应该执行一个HTTP请求并为此使用http.request()

如果在循环中调用doRequest(),我希望在前一个完成之后发出下一个请求(串行执行,一个接一个)。为了不弄乱回调和 Promises,我想使用 async/await 模式(使用 Babel.js 编译以在 Node 6+ 上运行)。

但是,我不清楚如何等待响应对象进行进一步处理以及如何将其作为doRequest() 的结果返回:

var doRequest = async function (options) {

    var req = await http.request(options);

    // do we need "await" here somehow?
    req.on('response', res => {
        console.log('response received');
        return res.statusCode;
    });
    req.end(); // make the request, returns just a boolean

    // return some result here?!
};

如果我使用 mocha 运行我当前的代码,并使用 HTTP 请求的各种选项,那么所有请求似乎都是同时发出的。他们都失败了,可能是因为doRequest() 实际上没有返回任何东西:

describe('Requests', function() {
    var t = [ /* request options */ ];
    t.forEach(function(options) {
        it('should return 200: ' + options.path, () => {
            chai.assert.equal(doRequest(options), 200);
        });
    });
});

【问题讨论】:

    标签: node.js async-await httprequest mocha.js babeljs


    【解决方案1】:

    async/await 使用承诺。只有当您的 async 函数 awaiting 返回一个 Promise 时,它​​们才会起作用。

    要解决您的问题,您可以使用 request-promise 之类的库或从您的 doRequest 函数返回一个承诺。

    这是使用后者的解决方案。

    function doRequest(options) {
      return new Promise ((resolve, reject) => {
        let req = http.request(options);
    
        req.on('response', res => {
          resolve(res);
        });
    
        req.on('error', err => {
          reject(err);
        });
      }); 
    }
    
    describe('Requests', function() {
      var t = [ /* request options */ ];
      t.forEach(function(options) {
        it('should return 200: ' + options.path, async function () {
          try {
            let res = await doRequest(options);
            chai.assert.equal(res.statusCode, 200);
          } catch (err) {
            console.log('some error occurred...');
          }
        });
      });
    });
    

    【讨论】:

    • 我认为第二个函数需要是一个异步函数。另外,这里没有错误处理。
    • 编辑添加您的建议。谢谢!
    • 此外,返回 Promise 的函数不需要声明为异步,因为它没有自己的 awaiting :) 捕获一些东西只是为了再次抛出它几乎不是错误处理:D console.log('oh noes!') 显然是进行错误处理的方法;)
    • 或者像return request(options).catch((e) => { });一样使用request-promise-native
    • 我认为您可能需要在承诺中调用req.end(),否则它永远不会真正发送请求?
    【解决方案2】:
    https.get('https://example.com', options, async res => {
        try {
            let body = '';
            res.setEncoding('utf-8');
            for await (const chunk of res) {
                body += chunk;
            }
            console.log('RESPONSE', body);
        } catch (e) {
            console.log('ERROR', e);
        }
    });
    

    【讨论】:

      【解决方案3】:
      const axios = require('axios');
      
      const url = "https://stackoverflow.com";
      const {data} = await axios.get(url);
      console.log("RES:" + data);
      

      【讨论】:

        【解决方案4】:

        您应该能够将 done 传递给您的 it 函数。然后,在异步请求完成后,您将在断言之后添加行 done()。如果有错误,你会将它传递给 done 函数,如 done(myError)

        https://mochajs.org/#asynchronous-code 了解更多信息

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-04-05
          • 2021-03-23
          • 2019-10-21
          • 1970-01-01
          • 2019-06-22
          • 1970-01-01
          • 1970-01-01
          • 2023-03-16
          相关资源
          最近更新 更多