Node.js强制等待函数完成

我在Node.js运行的程序中有一个for循环。 函数是xray包中的x(),我正在使用它来抓取网页中的数据,然后将这些数据写入文件。 这个程序用来刮〜100页是成功的,但我需要刮〜10000页。 当我尝试刮大量的页面时,文件被创build,但它们不包含任何数据。 我相信这个问题的存在是因为for循环没有等到x()返回到下一个迭代之前的数据。

有没有办法使节点等待x()函数完成,然后再继续下一个迭代?

//takes in file of urls, 1 on each line, and splits them into an array. //Then scrapes webpages and writes content to a file named for the pmid number that represents the study  //split urls into arrays var fs = require('fs'); var array = fs.readFileSync('Desktop/formatted_urls.txt').toString().split("\n"); var Xray = require('x-ray'); var x = new Xray();  for(i in array){ //get unique number and url from the array to be put into the text file name                number = array[i].substring(35);                url = array[i]; //use .write function of x from xray to write the info to a file x(url, 'css selectors').write('filepath' + number + '.txt');                                } 

注意:我正在抓取的一些页面没有返回任何值

你的代码的问题是,你不等待文件被写入文件系统。 比逐一下载文件更好的方法是一次完成,然后等待完成,而不是一个接一个地处理它们,然后继续下一个。

在nodejs中处理promise的一个推荐库是bluebird。

http://bluebirdjs.com/docs/getting-started.html

在更新后的示例中(见下文),我们遍历所有的url并开始下载,并跟踪promise,然后一旦文件写完,每个promise都被parsing。 最后,我们等待所有的承诺,使用Promise.all()

这是更新的代码:

 var promises = []; var getDownloadPromise = function(url, number){ return new Promise(function(resolve){ x(url, 'css selectors').write('filepath' + number + '.txt').on('finish', function(){ console.log('Completed ' + url); resolve(); }); }); }; for(i in array){ number = array[i].substring(35); url = array[i]; promises.push(getDownloadPromise(url, number)); } Promise.all(promises).then(function(){ console.log('All urls have been completed'); }); 

你不能让for循环等待asynchronous操作完成。 要解决这种types的问题,你必须做一个手动的迭代,你需要挂钩到asynchronous操作的完成function。 以下是如何工作的大纲:

 var index = 0; function next() { if (index < array.length) { x(url, ....)(function(err, data) { ++index; next(); }); } } next(); 

或者,也许这个;

 var index = 0; function next() { if (index < array.length) { var url = array[index]; var number = array[i].substring(35); x(url, 'css selectors').write('filepath' + number + '.txt').on('end', function() { ++index; next() }); } } next();