Node.js 在下载模块中使用承诺

Node.js 在下载模块中使用承诺,node.js,download,promise,bluebird,Node.js,Download,Promise,Bluebird,我用蓝鸟做承诺 我正试图向你保证这件事 以下是我的实现: Promise = require('bluebird'), download = require('download'); var methodNameToPromisify = ["download"]; function EventEmitterPromisifier(originalMethod) { // return a function return function promisified() {

我用蓝鸟做承诺

我正试图向你保证这件事

以下是我的实现:

Promise  = require('bluebird'),
download = require('download');

var methodNameToPromisify = ["download"];

function EventEmitterPromisifier(originalMethod) {
    // return a function
    return function promisified() {
        var args = [].slice.call(arguments);
        // Needed so that the original method can be called with the correct receiver
        var self = this;
        // which returns a promise
        return new Promise(function(resolve, reject) {
            // We call the originalMethod here because if it throws,
            // it will reject the returned promise with the thrown error
            var emitter = originalMethod.apply(self, args);

            emitter
                .on("response", function(data) {
                    resolve(data);
                })
                .on("data ", function(data) {
                    resolve(data);
                })
                .on("error", function(err) {
                    reject(err);
                })
                .on("close", function() {
                    resolve();
                });
        });
    };
};
download = { download: download };
Promise.promisifyAll(download, {
    filter: function(name) {
        return methodNameToPromisify.indexOf(name) > -1;
    },
    promisifier: EventEmitterPromisifier
});
然后使用它:

return download.downloadAsync(fileURL, copyTo, {});
我的问题是,它没有下载所有的文件(我有一个列表发送到此函数),我做错了什么?

发射器确实会发出多个数据事件,它接收到的每个数据块对应一个。但是,a只代表一个未来值,在您的情况下,您希望它是完整的响应

resolve
应该只调用一次,以使用传递的值实现承诺,然后进行结算。进一步的呼叫将没有任何效果-这就是为什么您只得到列表的前几部分

相反,您将需要累积所有数据,当流结束时,您可以用所有数据实现承诺

var Promise  = require('bluebird'),
    download = require('download'),
    Buffer   = require('buffer'); // should be global anyway

exports = {
    downloadAsync: function promisifiedDownload() {
        var args = arguments, self = this;

        return new Promise(function(resolve, reject) {
            // We call the originalMethod here because if it throws,
            // it will reject the returned promise with the thrown error
            var emitter = download.apply(self, args);
            var buffers = [];

            emitter.on("data", function(data) {
                buffers.push(data);
            }).on("error", function(err) {
                reject(err);
            }).on("close", function() {
                resolve(Buffer.concat(buffers));
            });
        });
    };
};
请注意,当您只想提出一个方法时,使用
promisifyAll
是非常荒谬的。为了简单起见,我省略了它


您还可以侦听传入对象,并将
数据
侦听器直接附加到它。然后,您可以使用而不是
close

是否有意(a)
download={download:download}覆盖
download=require('download'),和(b)
。on(“数据”,…)
中有这个空间吗?我的错,我会尝试修复它。虽然Angle文档中的示例完整地解释了它(如上所述),但想必
。on(“错误”,拒绝)
也可以工作?@Bergi,我必须删除它工作所需的(“缓冲区”),谢谢!这让事情变得更清楚了。啊!我的意思是上面的“Bluebird”文档,而不是“Angular”@agam360:Hm,我说“Buffer
类是一个全局类,这使得人们很少需要
要求('Buffer')
”,但我看不出它有什么问题。我的参考只是Bluebird API,在这一节中找到“function EventEmitterCompomissifier”。