Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/42.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Node.js异步下载多个文件_Javascript_Node.js_Asynchronous - Fatal编程技术网

Javascript Node.js异步下载多个文件

Javascript Node.js异步下载多个文件,javascript,node.js,asynchronous,Javascript,Node.js,Asynchronous,在尝试掌握node.js异步编码风格的过程中,我决定编写一个程序,读取包含一组URL的文本文件,下载每个文件。我开始编写一个只下载一个文件的函数,该函数运行良好,但在扩展逻辑以下载多个文件时遇到了问题 代码如下: var http = require("http"), fs = require("fs"), input = process.argv[2], folder = "C:/Users/Wiz/Downloads/", reg

在尝试掌握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");
        }
    }
};

如何构造代码,以便第一次下载的完成可以表示下一次下载的启动。请注意,这个练习只是为了学习,了解异步编码是如何工作的。在实践中,我确信有更好的工具可以下载多个文件。

首先尝试简单,它看起来像是复制粘贴代码,但并不了解它们的作用

做一个简单的循环,获取url,然后打印一些东西

var http = require('http');

URL = require('url').parse('http://www.timeapi.org/utc/now?format=%25F%20%25T%20-%20%25N')
URL['headers'] = {'User-Agent': 'Hello World'}


// launch 20 queries asynchronously
for(var i = 0; i < 20; i++) {
  (function(i) {
    console.log('Query ' + i + ' started');
    var req = http.request(URL, function(res) {
      console.log('Query ' + i + ' status: ' + res.statusCode + ' - ' + res.statusMessage);
      res.on('data', function(content){
        console.log('Query ' + i + ' ended - ' + content);
      });
    });

    req.on('error', function(err) {
      console.log('Query ' + i + ' return error: ' + err.message);
    });

    req.end();
  })(i);
}
所有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);
      http.get(url, function(response) {
                      var file =  fs.createWriteStream(filename);
                      response.on("end", function() {
                        file.end();
                      });
                      response.pipe(file);
                    })
    }
  });

什么不起作用?乍一看似乎不错。您确实意识到整个异步过程的一部分是,您不必等到一个完成后再启动另一个,对吗?Node js将发送多个下载请求,然后在返回时处理它们。无论一个请求是在另一个开始之前返回,还是它们以相同的顺序返回,都没有关系如果你处理得当,它们会被请求。它应该可以工作,但我得到一个通知:没有引发这样的文件或目录异常。我确实意识到整个异步工作应该是可行的,但事实并非如此,这就是为什么我实现了downloadQueue来序列化下载。我自己编写了每一行代码,所以我确实理解我在做什么,而不是从其他地方复制和粘贴。只是对它为什么不起作用感到困惑。