使用下载模块的promises

时间:2014-07-23 20:25:14

标签: node.js download promise bluebird

我正在使用蓝鸟作为承诺。

我想宣传download module

这是我的实施:

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, {});

我的问题是它没有下载所有文件(我有一个列表发送到这个函数),我做错了什么?

1 个答案:

答案 0 :(得分:2)

发射器会发出多个数据事件,每个事件接收一个块。但是,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是非常荒谬的。为简单起见,我省略了它

您也可以侦听传入的response对象,并将data侦听器直接附加到它。然后,您可以使用end event代替close