在 node.js 中使用递归模式循环

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10161894/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 15:32:25  来源:igfitidea点击:

Using recursive pattern loop with node.js

node.jsfor-loopdesign-patterns

提问by shane davis

ive been trying to use node.js to iterate through an array of cities and make an iterative request to google for directions on each (i then JSON.parse to abstract the drive times). I need to find a way to do this synchronously as otherwise i will just be requesting all the info from google on each city at once. I found a good pattern to use at http://tech.richardrodger.com/2011/04/21/node-js-%E2%80%93-how-to-write-a-for-loop-with-callbacks/but cannot get the callback to work. As you can see, im using a 'show' function to test the same. My code is as follows:

我一直在尝试使用 node.js 遍历一系列城市,并向 google 发出迭代请求以获取每个城市的方向(然后我使用 JSON.parse 来抽象驱动时间)。我需要找到一种方法来同步执行此操作,否则我将立即从 google 请求每个城市的所有信息。我在http://tech.richardrodger.com/2011/04/21/node-js-%E2%80%93-how-to-write-a-for-loop-with-callbacks找到了一个很好的模式/但无法使回调工作。如您所见,我使用“show”函数来测试相同的内容。我的代码如下:

var request = require('request');
var fs = require('fs');
var arr = ['glasgow','preston','blackpool','chorley','newcastle','bolton','paris','york','doncaster'];
//the function I want to call on each city from [arr]
function getTravelTime(a, b,callback){
 request('https://maps.googleapis.com/maps/api/directions/json?origin='+a+'&destination='+b+'&region=en&sensor=false',function(err,res,data){
 var foo = JSON.parse(data);
 var duration = foo.routes[0].legs[0].duration.text;
 console.log(duration);
 });
};

function show(b){
 fs.writeFile('testing.txt',b);
};


function uploader(i){
 if( i < arr.length ){
   show( arr[i],function(){
   uploader(i+1);
   });
 }
}
uploader(0)

The problem I have is that only the first city from the array is output and the callback/iteration never proceeds. Any ideas where im going wrong please? ?

我的问题是只输出数组中的第一个城市,并且回调/迭代永远不会进行。请问我哪里出错了??

回答by shane davis

Thanks for the pointers, was clearly down to my poor understanding of callbacks in javascript. Just reading JavaScript patterns by O'Reilly and hit the 'Callback pattern' sections - doh!

感谢您的指点,显然是由于我对 javascript 中的回调的理解很差。只需阅读 O'Reilly 的 JavaScript 模式并点击“回调模式”部分 - 哦!

For anyone who doesn't know, this is how the code will work:

对于不知道的人,这就是代码的工作方式:

var arr = ['glasgow','preston','blackpool','chorley','newcastle','bolton','paris','york','doncaster'];

function show(a,callback){
    console.log(a);
    callback();
}

function uploader(i){
  if( i < arr.length ){
    show(arr[i],
         function(){
          uploader(i+1)
         });
   };
}
uploader(0) 

回答by subbu

I was also facing issues like this, so I've written a recursive callback function which will act as a for loop but you can control when to increment. The following is that module, name as syncFor.jsand include this in your program

我也遇到过这样的问题,所以我编写了一个递归回调函数,它将充当 for 循环,但您可以控制何时递增。以下是该模块,名称为syncFor.js并将其包含在您的程序中

module.exports = function syncFor(index, len, status, func) {
    func(index, status, function (res) {
        if (res == "next") {
            index++;
            if (index < len) {
                syncFor(index, len, "r", func);
            } else {
                return func(index, "done", function () {
                })
            }
        }
    });
}

//this will be your program if u include this module
var request = require('request');
var fs = require('fs');
var arr = ['glasgow', 'preston', 'blackpool', 'chorley', 'newcastle', 'bolton', 'paris', 'york', 'doncaster'];
var syncFor = require('./syncFor'); //syncFor.js is stored in same directory
//the following is how u implement it

syncFor(0, arr.length, "start", function (i, status, call) {
    if (status === "done")
        console.log("array iteration is done")
    else
        getTravelTime(arr[i], "whatever", function () {
            call('next') // this acts as increment (i++)
        })
})


function getTravelTime(a, b, callback) {
    request('https://maps.googleapis.com/maps/api/directions/json?origin=' + a + '&destination=' + b + '&region=en&sensor=false', function (err, res, data) {
        var foo = JSON.parse(data);
        var duration = foo.routes[0].legs[0].duration.text;
        callback(); // call the callback when u get answer
        console.log(duration);
    });
};