无法将数据推送到空数组中,我使用 Node js 中的 https 模块从外部 api 获取数据

Not able to push data in an empty array, I'm getting that data from an external api, using https module in Node js

var https = require("https");
const arr = [];
for (let i = 1; i < 26; i++) {
  https.get(
    `https://jsonmock.hackerrank.com/api/countries?page=${i}`,
    (res) => {
      res.on("data", (data) => {
        JSON.parse(data).data.map((info, i) => {
          let { name } = info;
          arr.push(name);
          console.log(name);
        });
      });
    }
  );
}

console.log(arr);

当我刚刚记录 JSON.parse(data) 时,我正在我的控制台上获取所需的数据

但是当我试图将它推入一个数组时,它并没有发生,而是将一个空数组记录到控制台上

真的需要知道原因,因为我现在坚持了 3 天

您的问题是 https.get 的回调 - 即 (res) => 被调用 异步 - 因此, console.log(arr); 在 25 之前执行https.get 请求甚至被提出 - 如果你 console.log(arr);console.log(name); 你会看到 arr.push 确实有效 - 所以你假设你无法推送是不正确的

你正在推送到数组,你永远不会console.log数组中有数据

我想我可以建议您使用相当旧的 Node.js 版本 (14.16.0) 执行此操作的一种方法如下

var https = require("https");
function fn(callback) {
    const result = [];
    let done = 0;
    for (let i = 1; i < 26; i++) {
        https.get(`https://jsonmock.hackerrank.com/api/countries?page=${i}`, (res) => {
            res.on("data", (data) => {
                JSON.parse(data).data.map((info) => {
                    let { name } = info;
                    result.push(name);
                    console.log(name);
                });
                // keep track of how many requests have "completed"
                done = done + 1;
                // when all are done, call the callback
                if (done === 25) {
                    callback(result);
                }
            });
        });
    }
}
fn(arr => { // here is where arr is populated, nowhere else
    console.log(arr);
});

请注意,arr 只能在回调中访问 - 您将无法在 top-level 处访问 arr - 您唯一可能的方法是使用支持 top-level await 的 Node.js 版本 - 并将代码转换为使用 Promise(这是一项微不足道的任务)

不确定它是否重要,但不能保证 arr 中的名称顺序正确......例如,迭代 3 的结果可能会在迭代 4 之后推送,因为那是网络请求的性质,无法保证它们何时完成


As an aside. If you were to use the latest (18.1 at the time of writing) version of node.js - the above can be written like

const promises = Array.from({length:25}, async (_, i) => {
    const res = await fetch(`https://jsonmock.hackerrank.com/api/countries?page=${i+1}`);
    const data = await res.json();
    return data.map(({name}) => name);
});
const arr = (await Promise.all(promises)).flat(2);
console.log(arr);

注意事项是

  1. 原生 fetch - 与常规 node.js 方法相比,它使网络请求变得简单
  2. top-level await - 因此,您可以在代码 top-level 处使用 arr
  3. 6 行代码 vs 超过 20 行代码