【发布时间】:2015-11-27 08:39:59
【问题描述】:
在尝试掌握 node.js 异步编码风格的过程中,我决定编写一个程序来读取包含一堆 URL 的文本文件来下载和下载每个文件。我开始编写一个只下载一个文件的函数(效果很好),但是在扩展下载多个文件的逻辑时遇到了麻烦。
代码如下:
var http = require("http"),
fs = require("fs"),
input = process.argv[2],
folder = "C:/Users/Wiz/Downloads/",
regex = /(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?/,
urls = null,
url = "",
filename = "";
fs.readFile(input, "utf8", function(e, data) {
console.log("Reading file: " + input);
if (e) console.log("Got error:" + e.message);
urls = data.split("\n");
for (var i = urls.length; i--;) {
url = urls[i];
if (!url.match(regex)) continue;
filename = folder + url.substring(url.lastIndexOf('/') + 1);
downloadQueue.addItem(url, filename);
}
});
var downloadQueue = {
queue: [],
addItem: function(p_sSrc, p_sDest) {
this.queue.push({
src: p_sSrc,
dest: p_sDest
});
if (this.queue.length === 1) {
this.getNext();
}
},
getNext: function() {
var l_oItem = this.queue[0];
http.get(l_oItem.src, function(response) {
console.log("Downloading: " + l_oItem.dest);
var file = fs.createWriteStream(l_oItem.dest);
response.on("end", function() {
file.end();
console.log("Download complete.");
downloadQueue.removeItem();
}).on("error", function(error) {
console.log("Error: " + error.message);
fs.unlink(l_oItem.dest);
});
response.pipe(file);
});
},
removeItem: function() {
this.queue.splice(0, 1);
if (this.queue.length != 0) {
this.getNext();
} else {
console.log("All items downloaded");
}
}
};
如何构造代码,以便第一次下载的完成可以发出下一次下载的信号。请注意,此练习仅用于学习目的,以了解异步编码的工作原理。在实践中,我确信有更好的工具可以下载多个文件。
【问题讨论】:
-
什么不起作用?乍一看还不错。
-
您确实意识到整个异步事情的一部分是您不必等到一个完成才能启动另一个,对吧?
-
Node js 将发送多个下载请求,然后在它们返回时处理它们,如果一个在另一个开始之前返回,或者即使它们以相同的顺序返回,如果你处理它们,它们都无关紧要没错。
-
它应该可以工作,但我得到一个 ENOENT:没有抛出这样的文件或目录异常。我确实意识到整个异步操作应该可以工作,但事实并非如此,这就是我实现 downloadQueue 来序列化下载的原因。
标签: javascript node.js asynchronous