异步Javascript for循环

时间:2018-01-09 20:22:00

标签: javascript node.js asynchronous node-modules async.js

我的for循环只有一个问题,如果阻塞有效。 我必须从API是否获得温度并使用我的put方法将其放回到我的桌子中。 问题是我无法填补所有城市。 如何使用ASYNC(https://caolan.github.io/async)模块进行循环工作? 这是我的代码:



for (i in guests) {
        ville = i[ville_id];
        guest_id = i._id;
        if (ville) {
          results.push(req2 = http.get('http://api.openweathermap.org/data/2.5/weather?q=' + ville + ',france&APPID=xxx', function(res) {
            return res.on('data', function(chunk) {
              var options, test, url;
              test = chunk.toString();
              obj = JSON.parse(test);
              res = obj.main.temp;
              i[temp_id] = res;
              url = update_guest + guest_id.toString();
              options = {
                method: 'PUT',
                url: update_guest + guest_id,
                qs: {
                  api_key: 'xxx'
                },
                headers: {
                  'Cache-Control': 'no-cache',
                  'Content-Type': 'application/json'
                },
                body: {
                  '595f9b2a5ea9cb0004c21290': res
                },
                json: true
              };
              return request(options, function(error, response, body) {
                if (error) {
                  throw new Error(error);
                }
                return console.log(body);
              });
            });
          }));
        }
	  }




1 个答案:

答案 0 :(得分:0)

由于closures的工作方式,这是JavaScript中非常常见的问题。发生了什么事情是你的循环for (i in guests)在你的任何回调(function(res){...})有机会运行之前完成。您的回调引用变量i,但它们不会“记住”您发出HTTP请求时i的值。相反,当你的回调执行时,i将是guests中的最后一个值,因为你的for...in循环在你的回调执行时已经完成了。

例如,假设guests中有两个键,guest1guest2。这是将要发生的事情:

  1. 循环的第一次迭代运行。 i现在是guest1。第一个HTTP请求被触发。
  2. 循环的第二次迭代运行。 i现在是guest2。第二个HTTP请求被触发。
  3. 两个HTTP请求都已完成,您的回调已执行,但i设置为guest2。因此,对i的回调引用都是guest2
  4. 您需要做的是找到一种方法,让您的回调在您的请求被解雇时访问i 的值。您可以通过使用i作为参数的函数创建回调来实现此目的:

    for (i in guests) {
        ville = i[ville_id];
        guest_id = i._id;
        if (ville) {
          results.push(req2 = http.get('http://api.openweathermap.org/data/2.5/weather?q=' + ville + ',france&APPID=xxx', (function (localI) { return function(res) {
            return res.on('data', function(chunk) {
              // removing code for clarity
              localI[temp_id] = res;
              // removing code for clarity
              return request(options, function(error, response, body) {
                // removing code for clarity
              });
            });
          })(i)));
        }
      }
    

    您可以详细了解此方法here

    我所做的是创建了一个函数,它返回你的回调并获取参数localI。然后我立即将i作为该参数传递,并将localI设置为当前值i的回调返回。然后我将回调中的i引用更改为localI请注意,您在回调中对villeguest_id的引用也会遇到与i相同的问题。您需要将这些引用作为参数传递给好吧或在你的回调中声明它们。