承诺问题

Issue with Promise

我在下面的函数中遇到了一个小问题。 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

fs.stat 是回调类型函数,因此 return 不是 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. Promise.map() 运行s 并行操作每个数组元素,而不是串行操作。如果你想要它们 运行 串行,你可以将 {concurrency: 1} 作为选项传递给 Promise.map() 或使用 Promise.mapSeries().

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

  3. 您似乎在此处对 resolve()reject() 调用使用了 anti-pattern。你没有显示那些来自哪里的外部定义,但你应该只使用来自 Promise.map() 的承诺 returned 而不是那样做。

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

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(...)