使用承诺与下载模块 [英] Using promises with download module

查看:122
本文介绍了使用承诺与下载模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用蓝鸟的承诺。



我正在尝试承诺下载模块



这是我的实现:

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

var methodNameToPromisify = [download];

函数EventEmitterPromisifier(originalMethod){
//返回一个函数
return function promisified(){
var args = [] .slice.call(arguments);
//需要这样才能使用正确的接收器调用原始方法
var self = this;
//返回承诺
返回新的Promise(function(resolve,reject){
//我们在这里调用originalMethod,因为如果它抛出,
//它会拒绝返回的承诺与抛出的错误
var emitter = originalMethod.apply(self,args);

发送者
.on(response,function(data){
resolve(data);
})
.on(data,function(data){
resolve(data);
})
.on (error,function(err){
reject(err);
})
.on(close,function(){
resolve();
});
});
};
};
下载= {下载:下载};
Promise.promisifyAll(download,{
filter:function(name){
return methodNameToPromisify.indexOf(name)> -1;
},
promisifier: EventEmitterPromisifier
});

然后使用它:

  return download.downloadAsync(fileURL,copyTo,{}); 

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

解决方案

发射器发出多个数据事件,一个对于它接收的每个块。但是,a仅表示一个未来价值,在您的情况下,您希望这是完整的回应。



resolve 应该只被调用一次,以履行通过的价值的承诺,然后解决。进一步的电话将没有任何效果 - 这就是为什么你只得到列表的第一部分。



相反,你需要积累所有的数据,当流结束你可以履行所有的承诺。

  var Promise = require('bluebird'),
下载= require('download'),
Buffer = require('buffer'); //应该是全局的

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

返回新的Promise(function(resolve,reject){
//我们在这里调用originalMethod,因为如果它抛出,
//它会拒绝返回的承诺,错误
var emitter = download.apply(self,args);
var buffers = [];

emitter.on(data,function(data){
buffers.push(data);
})on(error,function(err){
reject(err);
})on(close (){
resolve(Buffer.concat(buffers));
});
});
};
};

注意使用 promisifyAll 当你只想承认一个方法。我已经省略了它的简单性



你也可以收听传入的 响应 对象,并将数据监听器直接附加到它。然后,您可以使用 结束事件而不是关闭


I am using bluebird for promises.

I am trying to promisify the download module.

Here is my implementation:

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

Then using it:

return download.downloadAsync(fileURL, copyTo, {});

My problem is that it doesn't download all of the files (I have a list sent to this function), what am I doing wrong?

解决方案

An emitter does emit multiple data events, one for every chunk it receives. However, a represents only one future value, in your case you want that to be the complete response.

resolve is supposed to be called only once, to fulfill the promise with the passed value, which is then settled. Further calls will have no effect - and that's why you get only the first parts of your list.

Instead, you will need to accumulate all the data, and when the stream ends you can fulfill the promise with all of it.

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

Notice it's quite nonsensical to use promisifyAll when you only want to promisify a single method. I've omitted it for simplicity

You might also listen for the incoming response object, and attach the data listener directly to it. You can then use the end event instead of close.

这篇关于使用承诺与下载模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆