Hi,
I just wanted to checkout this library and played a little bit with the pomisify stuff but it does not work for all methods:
var Promise = require('bluebird');
var createReadStream = Promise.promisify(require('fs').createReadStream);
var p1 = createReadStream('app.js').then(console.log);
setTimeout(function() {
console.log(p1);
}, 1000);
The p1 gets never fulfilled, no error, no success. I did test it for createWriteStream and it did not work, either.
createReadStream is not a callback taking function, from the docs:
Returns a function that will wrap the given nodeFunction. Instead of taking a callback, the returned function will return a promise whose fate is decided by the callback behavior of the given node function. The node function should conform to node.js convention of accepting a callback as last argument and calling that callback with error as the first argument and success value on the second argument.
There is no need to promisify createReadStream since it's a synchronous function, you can just call it normally and get the return value immediately back.
Oh gosh, you are right. It happened because I used promisifyAll (createReadStreamAsync), my bad. Sry 8-)
Something to note here is that createReadStream can fail in the future, and even if you created the stream inside a promise chain the error will be reported uncatched (and your application die). This is quite unfortunate, for example in the case of trying to open a missing file, you get a stream and in the next tick you get an exception.
You need to create a stream like this to avoid problems, although this is far from ideal:
function createReadStream(filename){
return new Promise(function(resolve, reject){
function onError(err){
reject(err);
}
function onReadable(){
cleanup();
resolve(stream);
}
function cleanup(){
stream.removeListener('readable', onReadable);
stream.removeListener('error', onError);
}
var stream = fs.createReadStream(filename);
stream.on('error', onError);
stream.on('readable', function(){
resolve(stream);
});
});
}
@petkaantonov have you give any thought about a proper way to make streams work well together with promises?
Your comment is really useful, thanks @manast !!
Regret digging up an old/closed thread, but I found @manast 's example useful and informative.
Hoping this will help anyone else who stumbles upon it: (tiny correction at the end)
function createReadStream(filename){
return new Promise(function(resolve, reject){
function onError(err){
reject(err);
}
function onReadable(){
cleanup();
resolve(stream);
}
function cleanup(){
stream.removeListener('error', onError);
stream.removeListener('readable', onReadable);
}
var stream = fs.createReadStream(filename);
stream.on('error', onError);
stream.on('readable', onReadable); // <-- small correction
});
}
Expanded for the Writable case:
function createWriteStream(filename){
return new Promise(function(resolve, reject){
function onError(err){
reject(err);
}
function onOpen(){
cleanup();
resolve(stream);
}
function cleanup(){
stream.removeListener('error', onError);
stream.removeListener('open', onOpen);
}
const stream = fs.createWriteStream(filename);
stream.on('error', onError);
stream.on('open', onOpen);
});
}
Most helpful comment
Something to note here is that createReadStream can fail in the future, and even if you created the stream inside a promise chain the error will be reported uncatched (and your application die). This is quite unfortunate, for example in the case of trying to open a missing file, you get a stream and in the next tick you get an exception.
You need to create a stream like this to avoid problems, although this is far from ideal:
@petkaantonov have you give any thought about a proper way to make streams work well together with promises?