承诺问题

时间:2016-04-22 13:29:21

标签: promise nodes bluebird

我的功能下面遇到了一个小问题。 Promise.map不会等待Folder.create完成并迭代下一个值。



Promise.map(name, function(na){
  return fs.stat(na.url, function(err, stats){
    if (typeof stats === 'undefined'){
      console.log("file doesn't exist");
      return Folder.create(na).then(function(fd){
        return mkdirp(root + product.url).then(function(){
          console.log("Folder Created");
          return null;
        });
      }, function(err){
        console.log(err);
        return reject({message: "Error when creating the folder"});
      });
    }
  });
}).then(function(){
  console.log('Iteration Done');
  return resolve({message: "Folder Created!"});
});

// I GOT : 
//file doesn't exist
//file doesn't exist
//file doesn't exist
//Iteration Done
//file doesn't exist
//file doesn't exist
//file doesn't exist
//Iteration Done
//Folder Created
//Folder Created
//Folder Created
//Folder Created
//Folder Created
//Folder Created




2 个答案:

答案 0 :(得分:0)

fs.stat是一个回调类型函数,因此不会返回Promise。你应该修改你的代码

// This might not work directly. I haven't tried to run it
Promise.map(name, function(na) {
    return new Promise(function(resolve, reject) {
        fs.stat(na.url, function(err, stats) {
            if (typeof stats === 'undefined') {
                console.log("file doesn't exist");
                Folder.create(na).then(function(fd) {
                    return mkdirp(root + product.url);
                }).then(function() {
                    console.log("Folder Created");
                    resolve();
                }).catch(function(err) {
                    console.log(err);
                    reject({
                        message: "Error when creating the folder"
                    });
                });
            } else {
                resolve();
            }
        });
    });
}).then(function() {
    console.log('Iteration Done');
    return {
        message: "Folder Created!"
    };
});

答案 1 :(得分:0)

这里有几个问题:

  1. Promise.map()并行运行每个数组元素的操作,而不是串行操作。如果您希望它们按顺序运行,您可以将{concurrency: 1}作为选项传递到Promise.map()或使用Promise.mapSeries()

  2. fs.stat()未返回承诺,因此您对Promise.map()的主回调未返回承诺,因此整个Promise.map()基础结构不知道如何等待任何你的结果。您可以宣传fs.stat()来解决该问题。

  3. 您似乎在resolve()reject()来电使用了anti-pattern。您没有显示那些来自的外部定义,但您应该只使用从Promise.map()返回的承诺而不是这样做。

  4. 以下是它们如何成功并行运行:

    var fs = Promise.promisifyAll(require('fs'));
    
    Promise.map(name, function(na){
      return fs.statAsync(na.url).then(function(err, stats){
        if (typeof stats === 'undefined'){
          console.log("file doesn't exist");
          return Folder.create(na).then(function(fd){
            return mkdirp(root + product.url).then(function(){
              console.log("Folder Created");
              return null;
            });
          }, function(err){
            console.log(err);
            return Promise.reject({message: "Error when creating the folder"});
          });
        }
      });
    }).then(function(){
      console.log('Iteration Done');
      return ({message: "Folder Created!"});
    });
    

    如果您想使用Bluebird顺序运行您的操作,可以将{concurrency: 1}传递给Promise.map()

    Promise.map(name, fn, {concurrency: 1}).then(...);
    

    或使用:

    Promise.mapSeries(name, fn).then(...)