对大文件上JSON输出的node.js刮取器的控制stream程的改进

我是新来的Node.js的asynchronous控制stream,我的刮板工作,但我不禁想到,必须有一个更优化(优雅?)的方式做到这一点,我打开使用其他节点库。 进一步来说:

  1. 我觉得目前的控制stream程(所有的callback)都很难理解,但也许是因为这对我来说是新的。 似乎有几个库控制stream量,我应该使用它?
  2. 最初,我的代码首先完成了所有request ,parsing并保存所有records = [] ,而不是处理将所有内容写入文件。 我在这里改变了代码,这样它会为for循环中的每个loggingrequest - parse - append ,我想确认这种方法对于大量的请求是否更好。
  3. 以JSON格式写入logging引起了一些痛苦,目前我必须调用startStep来追加[ first,然后使用(flag? function(){flag = false; return "";}() : ",")来决定是否是第一条logging,如果不是先追加逗号,则追加所有logging,最后追加] 。 再次,我很好奇是否有更好的方法来做到这一点。
  4. 为了迭代,我在全局范围声明了这个列表,并且使用list.shift()遍历下一个项目,现在看起来好了,但是我认为这会导致大规模的副作用。 我的直觉是我应该通过这个数组作为一个参数。 再次,我想在这一点上得到确认。

     var fs = require('fs'); var request = require("request"); var cheerio = require("cheerio"); function appendFile(_input, callback){ fs.appendFile("./TED/alltalk3.json", _input, function(err){ if(err){ console.log("input is" + _input + "error is :" + err); } else{ callback(); } }); } function startStep(){ appendFile("[", function(){ console.log("--start--"); getOneDay(list.shift()); }) } function finalStep(){ appendFile("]", function(){ console.log("--end--"); return; }) } var flag = true; // first item no comma function getOneDay(itm){ if(itm){ request("http://www.ted.com/talks/view/id/" + itm, function(error, response, body) { var $ = cheerio.load(body) var record = {}; record["title"] = $("#altHeadline").text(); appendFile( (flag? function(){flag = false; return "";}() : ",") + (JSON.stringify(record, null, 4)), function(){ return getOneDay(list.shift());; } ) }); } else{ return finalStep(); } } var list = []; for(var i = 1; i < 5; i++){ list.push(i); } startStep(); 

强烈build议您查看https://github.com/caolan/async – 特别是forEachSeries方法 – 它看起来正是您所需要的。

我也可以推荐在这种情况下使用fs同步方法。 不build议对服务使用阻塞方法,但对于类似shell的脚本,这是可以的。

你想用你的代码实现的是一个有限状态机 (FSM),这是在asynchronous编程中使用的常见模式。 有些语言内置了对。 例如,C#5.0具有async/await ,通过为我们提供熟悉的线程代码stream程,大大简化了asynchronous编程。

已经有一些尝试为JavaScript带来async/await 。 我相信,在Node.js和所有主要的Web浏览器中对它的全面支持只是时间问题。

在此之前,JavaScript中asynchronous代码stream的最常见模式是Promise 。 它代表将来要完成的操作的结果,并允许在完成时采取一个JavaScriptcallback函数。 我build议你坚持这个模式与您的代码。

更多资源: