2016-04-22 9 views
0

私は以下の機能に少し問題があります。 Promise.mapは、Folder.createが終了して次の値を反復するのを待つことはありません。Promiseに関する問題

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

+0

'if(typeof stats === 'undefined'){'? – Ioan

+0

残念ながらいいえ、何も変わりません – musecz

答えて

0

のようなものであるためにあなたのコードを変更する必要があります

  1. Promise.map()はないシリアル、パラレルの各配列要素のための操作を実行します。それらを連続して実行したい場合は、Promise.map()にオプションとして{concurrency: 1}を渡すか、Promise.mapSeries()を使用します。

  2. fs.stat()Promise.map()にあなたの主なコールバックが全体Promise.map()インフラはあなたの結果のいずれかを待つ方法を知らないので、約束を返さないように約束を返しません。あなたはその問題を解決するためにfs.stat()を約束することができます。

  3. ここでは、resolve()reject()コールでanti-patternを使用しているようです。それらがどこに由来するかという外側の定義は表示されませんが、それを行うのではなく、Promise.map()から返された約束を使用するだけです。ここで

は、彼らが成功し、並列に実行することができます方法は次のとおりです。

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!"}); 
}); 

あなたがブルーバードとシリアルあなたの操作を実行したい場合は、Promise.map(){concurrency: 1}を渡すことができます。

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

か使用:

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

最近のBluebirdでは、 'mapSeries'を使うべきです。これはまた、期待通りの順序でマップされます。 – Bergi

+0

@Bergi - そのオプションを追加しました。 – jfriend00

+0

@ jfriend00私が与えた例を正確にするために、Promise.rejectを使用してPromise.mapループを終了し、これを呼び出すPromiseに戻ります。その方法を使用することはお勧めしませんか? – musecz

0

fs.statコールバック型の関数であり、したがって、プロミスを返しません。あなたは夫婦の問題がここにあります。この

// 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

OPが使用している[反パターン](https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns)を永続させるのではなく、 'fs.stat()'を呼び出すと、プレーンコールバックと約束を混ぜ合わせません。いつでも、あなたは '.then()'ハンドラの片方のアームに 'resolve()'を持ち、もう片方のアームや '.catch()'に 'reject()'を持っていれば、パターンとより高いレベルの約束を返す必要があります。 – jfriend00