异步/等待 Node.js https.get

Sys*_*ter 9 node.js async-await

我正在尝试使用 async / await 简化代码

但是在https.get使用 async / await 结构时有问题。

我知道如何使用第三方模块执行此操作,但更喜欢本机 node.jshttps模块。

下面的代码对我不起作用:

async function get_page() {

    const https = require('https')
    const url = 'https://example.com'

    const util = require('util')
    const https_get = util.promisify(https.get)

    const data = await https_get(url)

    do_awesome_things_with_data(data)
}
Run Code Online (Sandbox Code Playgroud)

此代码工作正常:

function get_page() {

    const https = require('https')
    const url = 'https://example.com'

    let data = ''

    https.get(url, res => {

        res.on('data', chunk => { data += chunk }) 

        res.on('end', () => {

           do_awesome_things_with_data(data)

        })
    }) 
}
Run Code Online (Sandbox Code Playgroud)

ste*_*web 18

https.get不会返回可以被承诺的东西,因为回调的签名不匹配(err, value),所以你不能等待它。

但是,您可以https.get像这样将调用包装在 Promise 中,然后在调用时等待get_page

const https = require('https')

async function get_page() {
    const url = 'https://example.com'

    return new Promise((resolve) => {
        https.get(url, res => {

            res.on('data', chunk => { data += chunk }) 

            res.on('end', () => {

               resolve(do_awesome_things_with_data(data));

            })
        }) 
    })
}

// usage

(async () => await get_page())()
Run Code Online (Sandbox Code Playgroud)

编辑

我已经更新了我的答案,包括https.get不能被承诺并移动require('https')到函数调用之外的注释。

  • `require()` 不应该在 `async` 函数中使用,因为它是同步的。在会被重复调用的函数中使用“require()”也是不好的做法,通常,“util.promisify()”也是如此。它们都应该移到函数之外。 (2认同)

Ste*_*gin 5

而不是承诺,推出自己的功能,或使用第 3 方库。Promise 无法包装https.get返回的内容。

// generic promise method for https
const requestPromise = ((urlOptions, data) => {
  return new Promise((resolve, reject) => {
    const req = https.request(urlOptions,
      (res) => {
        let body = '';
        res.on('data', (chunk) => (body += chunk.toString()));
        res.on('error', reject);
        res.on('end', () => {
          if (res.statusCode >= 200 && res.statusCode <= 299) {
            resolve({statusCode: res.statusCode, headers: res.headers, body: body});
          } else {
            reject('Request failed. status: ' + res.statusCode + ', body: ' + body);
          }
        });
      });
    req.on('error', reject);
    req.write(data, 'binary');
    req.end();
  });
});
Run Code Online (Sandbox Code Playgroud)

然后像这样调用它:

async function get_page() {
    const url = 'https://example.com'
    const data = await requestPromise({url, method:'GET'})
    do_awesome_things_with_data(data)
}
Run Code Online (Sandbox Code Playgroud)

或者简单地使用一个库,比如axios返回一个本地承诺,并处理额外的样板案例。