变量未定义node.js

时间:2015-05-19 20:55:26

标签: javascript node.js

我正在尝试使用Node.js从API获取响应,我想清理API响应并使用结果。

因此,为了访问第一个API,我有以下代码。

要存储和使用结果,我相信我需要全局存储JSON输出。

但是,我无法弄清楚如何做到这一点。

示例 -

var request = require('request');

request({url: 'https://www.car2go.com/api/v2.1/vehicles?loc=wien&oauth_consumer_key=car2gowebsite&format=json', json: true}, function(err, res, json) {
if (err) {
    throw err;
}
car2go = json.placemarks;
for (i = 0; i < car2go.length; i++) {
    delete car2go[i].address;
    delete car2go[i].charging;
    delete car2go[i].exterior;
    delete car2go[i].interior;
    delete car2go[i].smartPhoneRequired;
    delete car2go[i].vin
    car2go[i].vendor = 'car2go';
    car2go[i].city = 'wien';
    car2go[i].carmake = 'Smart';
    car2go[i].carmodel = 'Fortwo';
}
console.log(car2go);
});

这会打印出所需的结果,但我知道这是因为我的变量是在函数中定义的。

我想访问函数之外的变量。

要测试我是否可以这样做,我将代码更改为 -

var request = require('request');

request({url: 'https://www.car2go.com/api/v2.1/vehicles?loc=wien&oauth_consumer_key=car2gowebsite&format=json', json: true}, function(err, res, json) {
if (err) {
    throw err;
}
car2go = json.placemarks;
for (i = 0; i < car2go.length; i++) {
    delete car2go[i].address;
    delete car2go[i].charging;
    delete car2go[i].exterior;
    delete car2go[i].interior;
    delete car2go[i].smartPhoneRequired;
    delete car2go[i].vin
    car2go[i].vendor = 'car2go';
    car2go[i].city = 'wien';
    car2go[i].carmake = 'Smart';
    car2go[i].carmodel = 'Fortwo';
}
});

console.log(car2go);

但如果我这样做,我会得到

ReferenceError: car2go is not defined

我在Mac OS Yosemite(10.10.3)上运行Node v0.12.2。

不可否认,我对节点非常陌生,我对R,Python和PL SQL更熟悉。

2 个答案:

答案 0 :(得分:1)

在回调函数之外无法引用它,因为console.log行在调用回调函数之前运行。您必须将回调函数传递到请求API的原因是因为请求库需要在完成请求时调用该函数。同时,在等待回调函数触发时,您的应用会继续运行并执行其他操作(例如运行console.log行)。

也就是说,有许多方法可以处理异步代码。我最喜欢的方式是承诺。我使用名为bluebird的库来处理承诺。

var request = require('request');
var Promise = require('bluebird');
var requestP = Promise.promisify(request);

Promise.promisify(request)的调用会返回一个不接受回调函数的新函数,而是返回promise

requestP({ url: 'https://www.car2go.com/api/v2.1/vehicles?loc=wien&oauth_consumer_key=car2gowebsite&format=json', json: true })
  .spread(function(res, json) {
    var car2go = json.placemarks;
    for (i = 0; i < car2go.length; i++) {
      delete car2go[i].address;
      delete car2go[i].charging;
      delete car2go[i].exterior;
      delete car2go[i].interior;
      delete car2go[i].smartPhoneRequired;
      delete car2go[i].vin
      car2go[i].vendor = 'car2go';
      car2go[i].city = 'wien';
      car2go[i].carmake = 'Smart';
      car2go[i].carmodel = 'Fortwo';
    }
  })
  .then(function (car2go) {
    console.log(car2go);
  })
  .catch(function (err) {
    console.error(err);
  });
  

注意:.spread.then相同,除非解析的值是一个数组(因为传递给请求库的回调接受2个参数,bluebird将转换为promise解析为的数组).spread会将数组拆分为多个参数,这些参数传递给您赋予.spread的函数。

Promise.resolve(['hi', 'there']).then(function (result) {
  console.log(result); // "['hi', 'there']"
});

Promise.resolve(['hi', 'there']).spread(function (str1, str2) {
  console.log(str1); // 'hi'
  console.log(str2); // 'there'
});

您无法将该值一直返回到开始异步调用的相同上下文中,但您至少可以编写使用promises时看起来有些同步的代码。

如果没有承诺,你将被迫从函数内的函数内调用函数;)

答案 1 :(得分:0)

响应是异步的。这意味着回调函数将在稍后的某个时间被调用,因此在调用回调之前你的console.log(car2go)正在执行。

唯一能够可靠地使用响应的地方是回调内部或回调中调用的函数。你不能按照你想要的方式使用它。在Javascript中使用异步响应需要以异步方式进行编程,这意味着只在异步回调中处理结果和使用结果。

这里console.log()应该是:

var request = require('request');

request({url: 'https://www.car2go.com/api/v2.1/vehicles?loc=wien&oauth_consumer_key=car2gowebsite&format=json', json: true}, function (err, res, json) {
    if (err) {
        throw err;
    }
    car2go = json.placemarks;
    for (i = 0; i < car2go.length; i++) {
        delete car2go[i].address;
        delete car2go[i].charging;
        delete car2go[i].exterior;
        delete car2go[i].interior;
        delete car2go[i].smartPhoneRequired;
        delete car2go[i].vin
        car2go[i].vendor = 'car2go';
        car2go[i].city = 'wien';
        car2go[i].carmake = 'Smart';
        car2go[i].carmodel = 'Fortwo';
    }
    // here is where the result is available
    console.log(car2go);
});