我一直在尝试使用node.js迭代一系列城市,并发出一个迭代请求来谷歌搜索每个城市的方向(然后是JSON.parse来抽象驱动时间)。我需要找到一种同步执行此操作的方法,否则我将立即从每个城市的谷歌请求所有信息。我找到了一个在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+'®ion=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)
我遇到的问题是只输出数组中的第一个城市,并且回调/迭代永远不会继续。有什么想法,我出错了吗?
答案 0 :(得分:15)
感谢指点,显然是由于我对javascript中回调的理解不足。只需阅读O'Reilly的JavaScript模式并点击'回调模式'部分 - doh!
对于任何不知道的人,这是代码的工作方式:
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)
答案 1 :(得分:11)
我也面临这样的问题,所以我编写了一个递归回调函数,它将作为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 + '®ion=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);
});
};