Question

I am using the promise library bluebird with node 0.11.9 running with the flag --harmony

I have a simple working example:

var Promise = require('bluebird');
var fs = require('fs');
var readdirAsync = Promise.promisify(fs.readdir, fs);
var statAsync = Promise.promisify(fs.stat, fs);

Promise.spawn(function *() {
  var files = yield readdirAsync('./');
  var stats = yield files.map(function(file) { return statAsync(file); });
  console.log(stats);
  console.log('done');
});

This works fine and output the list of nodes' stats. But with the following version: there is no output at all:

var Promise = require('bluebird');
var fs = require('fs');
var readdirAsync = Promise.promisify(fs.readdir, fs);
var statAsync = Promise.promisify(fs.stat, fs);

Promise.spawn(function *() {
  var files = yield readdirAsync('./');
  var stats = yield files.map(statAsync);
  console.log(stats);
  console.log('done');
});

Any idea of why this doesn't work ?

Was it helpful?

Solution

The problem is unfortunately that Promise.promisify isn't perfect. It doesn't know how many arguments fs.stat should have. It passes through whatever arguments you give it, as well as the node style callback.

Array.prototype.map doesn't call the mapping function with a single argument. Instead it gives it the item, the index in the array, and a copy of the array. Therefore your second example looks like:

var Promise = require('bluebird');
var fs = require('fs');
var readdirAsync = Promise.promisify(fs.readdir, fs);
var statAsync = Promise.promisify(fs.stat, fs);

Promise.spawn(function *() {
  var files = yield readdirAsync('./');
  var stats = yield files.map(function(file, i, a) { return statAsync(file, i, a); });
  console.log(stats);
  console.log('done');
});

If the callback doesn't appear until the fourth argument, fs.stat will never call it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top