异步 JavaScript 编程中的 https.get 的 async / await 版本 vs promise 版本 vs 回调版本

async / await version of https.get vs promise version vs callback version in asynchronous JavaScript programming

提问人:Hamid 提问时间:3/25/2023 最后编辑:Hamid 更新时间:3/26/2023 访问量:79

问:

为什么 JS 中异步程序的这个异步/await 版本不给出任何输出?

async-await 版本:

const https = require('https');

async function getDataFromServer() {
  try {
    const response = await https.get('https://jsonplaceholder.typicode.com/posts/1');
    let data = '';
    response.on('data', (chunk) => {
      data += chunk;
    });
    response.on('end', () => {
      console.log(data);
    });
  } catch (error) {
    console.error(error);
  }
}

getDataFromServer();

而其他两个版本有效?

回调版本:

const https = require('https');

function getDataFromServer(callback) {
  https.get('https://jsonplaceholder.typicode.com/posts/1', (response) => {
    let data = '';
    response.on('data', (chunk) => {
      data += chunk;
    });
    response.on('end', () => {
      callback(data);
    });
  }).on('error', (error) => {
    console.error(error);
  });
}

getDataFromServer((data) => {
  console.log(data);
});

承诺版本:

const https = require('https');

function getDataFromServer() {
  return new Promise((resolve, reject) => {
    https.get('https://jsonplaceholder.typicode.com/posts/1', (response) => {
      let data = '';
      response.on('data', (chunk) => {
        data += chunk;
      });
      response.on('end', () => {
        resolve(data);
      });
    }).on('error', (error) => {
      reject(error);
    });
  });
}

getDataFromServer().then((data) => {
  console.log(data);
}).catch((error) => {
  console.error(error);
});

谢谢。

我在 JavaScript 中尝试了三个版本的简单异步编程示例(带有 callback、promise 和 async-await),但我无法弄清楚为什么 async/await 版本不能给出与其他两个版本相同的结果?即,控制台窗口中不显示任何内容。

javascript async-await promise 回调

评论

1赞 Nick Parsons 3/25/2023
只有当它右手边的东西是可(即:承诺)时,才真正有意义。是否返回 Promise?awaithttps.get()
2赞 Unmitigated 3/25/2023
https.get不返回 a ,因此您不能真正等待它。Promise
1赞 Pointy 3/25/2023
我认为这个问题是相关的。我不认为返回 Promise 实例。https.get()
0赞 gre_gor 3/25/2023
responsefrom you async/await version 是 的实例,from the callback 是 的实例。它们不一样。ClientRequestresponseIncomingMessage

答:

2赞 jfriend00 3/25/2023 #1

为什么 JS 中异步程序的这个异步/await 版本不给出任何输出?

因为你只是用错了。该函数需要回调才能获得响应。它不支持任何形式的承诺。https.get()

因此,当您执行此操作时:

const response = await https.get('https://jsonplaceholder.typicode.com/posts/1');

这没有做任何有用的事情,因为它不返回承诺 - 相反,它返回一个对象,如果它是 POST 或您需要编写正文的其他类型的请求,您将写入该对象。 仅在等待解析为您想要的值的承诺时才有用。因此,由于您没有传递回调,因此您永远不会获得响应对象,而是将事件处理程序附加到从不发出 or 事件的请求对象,因此似乎“什么都没有”发生。实际上,请求已发送,但您没有合适的侦听器来获取响应。awaithttps.get()http.ClientRequestawaitdataend

相反,您必须通过传递回调函数来获取对象,就像在其他两个示例中所做的那样。response


注意:是一个非常低级的 API,本身不支持 promise。对于只想发送请求并使用 promise 获取整个响应的代码,使用具有内置 promise 支持的更高级别的 API 将节省代码。热门选项包括:https.get()

fetch()
got()
axios()

从 nodejs v18 开始,nodejs 中现在存在与浏览器中使用的相同实现:fetch()

async function getDataFromServer() {
    const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
    const results = await response.json();
    console.log(results);
}

getDataFromServer().catch(err => {
    console.log(err);
});

我个人最喜欢的是 got() 库(我只是喜欢编程接口,它具有丰富的功能集)。

const got = require('got');

async function getDataFromServer() {
    const result = await got('https://jsonplaceholder.typicode.com/posts/1').json();
    console.log(result);
}

getDataFromServer().catch(err => {
    console.log(err);
});
0赞 balaji balu 3/25/2023 #2

我假设您正在使用 nodejs https 模块来获取数据。它仅支持回调。

要使 async/await 成为 async/await,请以这种方式调用 promise 版本

const https = require('https');

function getDataFromServer() {
  return new Promise((resolve, reject) => {
    https
      .get('https://jsonplaceholder.typicode.com/posts/1', (response) => {
        let data = '';
        response.on('data', (chunk) => {
          data += chunk;
        });
        response.on('end', () => {
          resolve(data);
        });
      })
      .on('error', (error) => {
        reject(error);
      });
  });
}

//wrap your promise based version as async call
async function getDataFromServerAsync() {
  // return the response
  return await getDataFromServer();
}

//call the async function
getDataFromServerAsync().then((resp) => {
  console.log('Response received: ', resp);
});

评论

2赞 jfriend00 3/25/2023
你的功能没有意义。这与直接呼叫相同。两者都返回一个解析为相同值的 promise。getDataFromServerAsync()getDataFromServer()