为什么这个HTTP代码没有返回任何数据?

时间:2017-09-22 18:36:34

标签: javascript node.js

我正在研究Node.JS项目,我正在尝试向API发出HTTP请求。我正在尝试调试此代码,但无法弄清楚为什么'responseData'没有设置。

var responseData = "initial";
var options = {
    hostname:'api.insight.ly',
    path: '/v2.1/contacts', 
    headers: {
        'Authorization': 'Basic (API key here)',
        'Accept-Encoding': 'gzip'
    }
};
http.get(options, (response) => {
    const statusCode = response.statusCode;
    let error;
    if (statusCode !== 200) {
        error = new Error('Request Failed.\n' +
                        `Status Code: ${statusCode}`);
    }
    if (error) {
        responseData = "ERROR";
        // consume response data to free up memory
        response.resume();
        return;
    }
      response.setEncoding('utf8');
      let rawData = '';
    response.on('data', (chunk) => rawData += chunk);
    response.on('end', () => {
    try {
        const parsedData = JSON.parse(rawData);
        responseData = parsedData
    } catch (e) {
        responseData = e.message;
    }
  });
}).on('error', (e) => {
    responseData = (`Got error: ${e.message}`);
  });
response.end(responseData);

我相信我已经处理了每个错误的情况,无论如何,responseData应该成为错误或JSON数据。但是,在此函数结束时responseData是最初的。我错过了什么?

1 个答案:

答案 0 :(得分:0)

您遇到了范围/关闭问题,并且误解了Javascript事件循环。此代码不按您声明的顺序运行。您在第一行声明并分配responseData变量。然后你宣布选项。然后,您告诉http核心模块使用这些选项发起GET请求,并为其提供回调(response)=>{...}。然后,您将responseData传递给response.end。在此范围内,response甚至不存在;它作为参数传递给您提供http.get方法的回调。事件监听器(response.on('data'...response.on('end'...)是实际操作的位置。

您的代码实际上是按照以下顺序执行的:

-> assign responseData
-> assign options
-> call http.get
-> call response.end with responseData
-> call http.get callback
-> set response.on 'data' callback
-> set response.on 'end' callback
-> call response.on 'data' callback with chunk1
-> call response.on 'data' callback with chunk2
-> etc...
-> call response.on 'end' callback
-> parse responseData

事实上,我认为您甚至不需要进行response.end调用,如果您正在制作从服务器发送的响应,那么这似乎更有必要。实际上只是想从其他API发送的响应中积累数据。您真正需要的是在“结束”事件结束时传递累积responseData的功能。

var responseData = "initial";
var options = {
    hostname:'api.insight.ly',
    path: '/v2.1/contacts', 
    headers: {
        'Authorization': 'Basic (API key here)',
        'Accept-Encoding': 'gzip'
    }
};
http.get(options, (response) => {
    const statusCode = response.statusCode;
    let error;
    if (statusCode !== 200) {
        error = new Error('Request Failed.\n' +
                        `Status Code: ${statusCode}`);
    }
    if (error) {
        responseData = "ERROR";
        // consume response data to free up memory
        response.resume();
        return;
    }
      response.setEncoding('utf8');
      let rawData = '';
    response.on('data', (chunk) => rawData += chunk);
    response.on('end', () => {
    try {
        const parsedData = JSON.parse(rawData);
        responseData = parsedData
        //do something with your data here
    } catch (e) {
        responseData = e.message;
    }
  });
}).on('error', (e) => {
    responseData = (`Got error: ${e.message}`);
  });