我正在使用蓝鸟作为承诺。
我想宣传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, {});
我的问题是它没有下载所有文件(我有一个列表发送到这个函数),我做错了什么?
答案 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
。