【问题标题】:Save JSON data from Node.js Get request to global variable or file将来自 Node.js Get 请求的 JSON 数据保存到全局变量或文件
【发布时间】:2018-05-09 18:42:59
【问题描述】:

我需要将 GET 请求中的数据保存到变量中,然后将其保存在文件中。但是,在某些情况下,GET 请求不会将数据保存到全局变量中。

var fs = require("fs");
var http = require("http");
var request = require('request');

var tmp_json = {};
var g_last = 0;
var data = {};

 //request 1
http.get('server:api', (resp) => {
  let data = '';

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

  resp.on('end', () => {
    tmp_json.server1 = {};
    tmp_json.server1 = JSON.parse(data);
    g_last = tmp_json.height; // 100500
    console.log(g_last); // 100500
  });

}).on("error", (err) => {
  console.log("Error: " + err.message);
});

 //request 2
http.get('server2:api', (resp) => {
  let data = '';

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

  resp.on('end', () => {
    tmp_json.server2 = {};    
    tmp_json.server2 = JSON.parse(data);
    g_last = tmp_json.height; // 256
    console.log(g_last); // 256
  });

}).on("error", (err) => {
  console.log("Error: " + err.message);
});

console.log(g_last); // 0

data = JSON.stringify(tmp_json);
fs.writeFile('data.json', data, 'utf8'); // empty file

我也尝试使用 fs.createWriteStream 来实现,但我可以再次将一个请求保存到文件中,但如果有多个请求,我只能捕获缓冲区数据。

【问题讨论】:

标签: javascript json node.js api


【解决方案1】:

您的问题是 request1 和 request2 在您编写文件时发生。这是因为节点的异步性质。执行顺序如下所示:

  1. 声明空变量
  2. Request1 出去
  3. Request2 出去
  4. 将空变量写入文件
  5. Request1 返回并写入变量
  6. Request2 返回并写入变量

解决此问题的一种方法是使用Promises。以下允许在Promise.all([ ... ]) 中的承诺解决后执行then 中的函数:

var fs = require("fs");
var http = require("http");

var tmp_json = {};
var g_last = 0;
var data = {};

 //request 1
var req1 = new Promise((resolve, reject) => {
  http.get('server:api', (resp) => {
    let data = '';

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

    resp.on('end', () => {
      tmp_json.server1 = {};
      tmp_json.server1 = JSON.parse(data);
      g_last = tmp_json.height; // 100500
      console.log(g_last); // 100500
      resolve()
    });

  }).on("error", (err) => {
    console.log("Error: " + err.message);
    reject(error)
  });
});

 //request 2
var req2 = new Promise((resolve, reject) => {
  http.get('server2:api', (resp) => {
    let data = '';

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

    resp.on('end', () => {
      tmp_json.server2 = {};
      tmp_json.server2 = JSON.parse(data);
      g_last = tmp_json.height; // 256
      console.log(g_last); // 256
      resolve()
    });

  }).on("error", (err) => {
    console.log("Error: " + err.message);
    reject(error)
  });
});

Promise.all([ req1, req2 ]).then(() => {
  console.log(g_last);
  data = JSON.stringify(tmp_json);
  fs.writeFile('data.json', data, 'utf8');
})

编辑:

function handleGet (url) {
  return new Promise((resolve, reject) => {
    http.get(url, (resp) => {
      let data = '';

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

      resp.on('end', () => {
        tmp_json.server1 = {};
        tmp_json.server1 = JSON.parse(data);
        g_last = tmp_json.height; // 100500
        console.log(g_last); // 100500
        resolve()
      });

    }).on("error", (err) => {
      console.log("Error: " + err.message);
      reject(error)
    });
  })
}

// Then use it
Promise.all([
  handleGet('http://google.ca'),
  handleGet('http://somesite.com')
])

【讨论】:

  • 感谢它的工作真棒!但是我可以像带参数的函数一样调用它吗? IE。如果我需要将服务器的url地址设置为参数?
  • @MAxShvedov 您可以编写一个返回承诺的函数,我将在我的答案中添加一个示例。
  • 节点说我:UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: http.get is not a function
猜你喜欢
  • 1970-01-01
  • 2014-12-05
  • 2018-02-22
  • 1970-01-01
  • 2019-08-17
  • 2021-01-30
  • 1970-01-01
  • 2017-09-02
  • 1970-01-01
相关资源
最近更新 更多