Node.js,callback,asynchronous,命令行

使用下面的代码,我一直在试图下载一个URL,保存到文件,并检查该文件中是否有任何html标签(我想检查的标签在checks.json中)。 我需要从命令行运行这个,我想我需要JavaScript语言的asynchronous,callbackfunction。

而且我迷失在这一点上。 我无法做到这一点。 我的问题是,从命令行我总是得到该文件不存在的错误。

我知道它需要等到它被下载,然后运行检查。 但是,似乎每次运行代码,该函数不被调用。 我不知道为什么。

所以我需要了解的是:

我可以如何从命令行运行它,下载URL,将其保存到文件中,使用checks.json进行检查并将结果打印到控制台。

谢谢。

var fs = require('fs'); var program = require('commander'); var cheerio = require('cheerio'); var rest = require('restler'); var HTMLFILE_DEFAULT = "index.html"; var CHECKSFILE_DEFAULT = "checks.json"; var URLFILE_DEFAULT = "downloaded.html"; var assertFileExists = function(infile) { var instr = infile.toString(); if(!fs.existsSync(instr)) { console.log("%s does not exist. Exiting.", instr); process.exit(1); // http://nodejs.org/api/process.html#process_process_exit_code } return instr; }; var cheerioHtmlFile = function(htmlfile) { return cheerio.load(fs.readFileSync(htmlfile)); }; var loadChecks = function(checksfile) { return JSON.parse(fs.readFileSync(checksfile)); }; var checkHtmlFile = function(htmlfile, checksfile) { $ = cheerioHtmlFile(htmlfile); var checks = loadChecks(checksfile).sort(); var out = {}; for(var ii in checks) { var present = $(checks[ii]).length > 0; out[checks[ii]] = present; } return out; }; var clone = function(fn) { // Workaround for commander.js issue. // http://stackoverflow.com/a/6772648 return fn.bind({}); }; var downAnd2File = function() { rest.get('http://www.wired.com/').on('complete', function(result) { if (result instanceof Error) { sys.puts('Error: ' + result.message); this.retry(5000); // try again after 5 sec } else { fs.writeFile(__dirname + '/downloaded.html', result, function(err) { if (err) throw err; console.log('Saved!'); }); } }); downAnd2File(checkHtmlFile); } if(require.main == module) { program .option('-c, --checks <check_file>', 'Path to checks.json', clone(assertFileExists), CHECKSFILE_DEFAULT) .option('-f, --file <html_file>', 'Path to index.html', clone(assertFileExists), HTMLFILE_DEFAULT) .option('-u, --url <html_file>', 'Path to downloaded url', clone(assertFileExists), URLFILE_DEFAULT) /////////////// .parse(process.argv); var down2FileAndCheck = downAnd2File(checkHtmlFile(program.url, program.checks)); var checkJson = checkHtmlFile(program.file, program.checks); var outJson = JSON.stringify(checkJson, null, 4); console.log(outJson); } else { exports.checkHtmlFile = checkHtmlFile; } 

你似乎不明白在node.js中callback是如何工作的 你将需要做一些关于它在stackoverflow或其他地方阅读。

我重写了你的程序(但没有testing它),研究它并询问我是否有任何问题。

 // halts if the provided filename doesn't exist function assertFileExists(filename) { if (!fs.existsSync(filename)) { console.log("%s does not exist. Exiting.", filename); process.exit(1); } return filename; } // loads checks from a file function loadChecks(checksfile) { return JSON.parse(fs.readFileSync(checksfile)).sort(); } // checks html function checkHtml(html, checks) { $ = cheerio.load(html); var out = {}; for(var ii in checks) { var present = $(checks[ii]).length > 0; out[checks[ii]] = present; } return out; } // loads html from a file and checks it // for exports only function checkHtmlFile(filename, checks) { return checkHtml(fs.readFileSync(filename), checks); } // downloads html from the internet // callback is called with two arguments: err, html // where err is null if there is no error function download(url, callback) { var resp = rest.get(url); resp.on('complete', function(result) { if (result instanceof Error) { // callback(result); sys.puts('Error: ' + result.message); this.retry(5000); // try again after 5 sec return; } callback(null, result); }); } if (require.main == module) { program .option('-c, --checks <check_file>', 'Path to checks.json', assertFileExists, CHECKSFILE_DEFAULT) .option('-f, --file <html_file>', 'Path to index.html', assertFileExists, HTMLFILE_DEFAULT) .option('-u, --url <url>', 'Path to downloaded url') /////////////// .parse(process.argv); // this function loads checks & checks html function check(err, html) { if (err) { console.log('Error getting html: ' + err); process.exit(1); } var checks = loadChecks(program.checks); var checkJson = checkHtml(html, checks); var outJson = JSON.stringify(checkJson, null, 4); console.log(outJson); } if (program.url) { // download the provided url and then check the html download(program.url, check); } else if (program.file) { // load html from a file and then check it fs.readFile(program.file, check); } } else { exports.loadChecks = loadChecks; // for loading checks exports.checkHtmlFile = checkHtmlFile; // for checking a file } 

正如Mak所说的,你并不需要下载并保存你刚才提取的html。

这是对原始代码的一个小的重构。 这个想法是获取HTML(无论是从url或保存的文件)。 一旦结果/数据准备就绪,请调用该方法运行内容检查。

 function checkHtml(err, html){ if (err){ console.log('Error: ' + err); process.exit(1); } var checkJson = checkHtmlFile(html, program.checks); var outJson = JSON.stringify(checkJson, null, 4); console.log(outJson); } if(require.main == module){ program .option('-c, --checks <check_file>', 'Check path', clone(assertFileExists), CHECKS_DEF) .option('-f, --file <html_file>', 'File path', clone(assertFileExists), HTML_DEF) .option('-u, --url <url_pointer>', 'Url link that needs to be graded') .parse(process.argv); if (program.url){ rest.get(program.url) .on('complete', function(result){ checkHtml((html instanceof Error), result); }); } else { fs.readFile(program.file, checkHtml); } } 

希望这可以帮助。

以防万一你的问题发生在任何JS代码执行之前:

您可能想要使文件可执行

  chmod +x <filename> 

并在您的文件顶部添加此声明:

  #!/usr/bin/env node 

对不起,如果已经是这样的话