2017-01-12 11 views
1

約束事とデータ返信を使用してデータの配列を反復処理する方法はありますか?私はいくつかのpromises.push(asyncFunc)メソッドを見たことがありますが、私の配列からのエントリのいくつかは失敗しますので、私はそれを使うことができません。配列を反復して約束を待つ

var filesFromDisk = [ 
    '41679_4_2015-09-06_17-02-12.mp4', 
    '41679_4_2015-09-06_17-02-12.smil', 
    '41680_4_2015-09-09_10-44-05.mp4' 
]; 

start(filesFromDisk) 
    .then((data) => { 
     console.log(data); // Want my data here 
}); 

私はデータが返さする理由である別のファイルからstart(dbFiles)を開始します。

function start(dbFiles) { 
    var listOfFiles = [], 
     promises = []; 
    return new Promise((fulfill, reject) => { 
     for (var i = 0; i < dbFiles.length; i++) { 
      getMp4(dbFiles[i]) 
       .then((data) => { 
        listOfFiles = listOfFiles.concat(data); 
        console.log(listOfFiles); 
       }) 
     } 
     fulfill(listOfFiles) // Need to happen AFTER for loop has filled listOfFiles 
    }); 
} 

だから私のアレイ内のすべてのエントリのために私は、新しい拡張子を持つファイルが存在するかどうかを確認し、そのファイルを読むことをお勧めします。拡張子の付いたファイルが存在しない場合、私は元のファイルを完成させます。マイPromise.allチェーンの作品と、すべてのデータは、(getMp4(dbFiles[i])

function getMp4(filename) { 
    var mp4Files = []; 
    var smil = privateMethods.setSmileExt(localData.devPath + filename.toString()); 
    return new Promise((fulfill, reject) => { 
     Promise.all([ 
      privateMethods.fileExists(smil), 
      privateMethods.readTest(smil) 
     ]).then(() => { 
      readFile(filename).then((files) => { 
       fulfill(files) 
      }); 
     }).catch((err) => { 
      if (!err.exists) fulfill([filename]); 
     }); 
    }); 
} 

function readFile(filename){ 
    var filesFromSmil = []; 
    return new Promise((fulfill, reject) => { 
     fs.readFile(localData.devPath + filename, function (err, res){ 
      if (err) { 
       reject(err); 
      } 
      else { 
       xmlParser(res.toString(), {trim: true}, (err, result) => { 
        var entry = JSON.parse(JSON.stringify(result.smil.body[0].switch[0].video)); 
        for (var i = 0; i < entry.length; i++) { 
         filesFromSmil.push(privateMethods.getFileName(entry[i].$.src)) 
        } 
       }); 
       fulfill(filesFromSmil); 
      } 
     }); 
    }); 
}; 

getMp4でPromise.allチェーンのメソッドの上にforループで返される - 私が知っているこれらに問題を持っていません。

var privateMethods = { 
    getFileName: (str) => { 
     var rx = /[a-zA-Z-1\--9-_]*.mp4/g; 
     var file = rx.exec(str); 
     return file[0]; 
    }, 
    setSmileExt: (videoFile) => { 
     return videoFile.split('.').shift() + '.smil'; 
    }, 
    fileExists: (file) => { 
     return new Promise((fulfill, reject) => { 
      try { 
       fs.accessSync(file); 
       fulfill({exists: true}) 
      } catch (ex) { 
       reject({exists: false}) 
      } 
     }) 
    }, 
    readTest: (file) => { 
     return new Promise((fulfill, reject) => { 
      fs.readFile(file, (err, res) => { 
       if (err) reject(err); 
       else fulfill(res.toString()); 
      }) 
     }) 
    } 
} 
+0

並列または順次実行する必要がありますか? –

+0

開始点のデータが.then()で完了している限り、これらは並列で実行できます。私があなたを正しく理解していれば、 –

答えて

2

あなたがそれらを並列に実行する必要がある場合、Promise.allはあなたが望むものである:彼らはすべて完了し、その後で解決するまで

function start(dbFiles) { 
    return Promise.all(dbFiles.map(getMp4)); 
} 

ファイルや待機のすべてについてgetMp4動作を開始結果の配列。 (。getMp4値、インデックス、およびdbFiles arary   —へのAAの参照複数の引数  —を受け取ることになりますが、それは最初に使用しているので、それは大丈夫です)

使用法:

start(filesFromDisk).then(function(results) { 
    // `results` is an array of the results, in order 
}); 

完全性を保つために、順番に実行する必要がある場合は、パターンを使用できます。

function start(dbFiles) { 
    return dbFiles.reduce(function(p, file) { 
     return p.then(function(results) { 
      return getMp4(file).then(function(data) { 
       results.push(data); 
       return results; 
      }); 
     }); 
    }, Promise.resolve([])); 
} 

同じ使用法。 []で解決された約束からどのように開始したら、配列を受け取るthenハンドラの束をキューに入れ、getMp4コールを行い、結果が配列に戻ってそれを返します。最終的な解像度値は塗りつぶしの配列です。

+0

@Alnitak:** OMG **、本当に '.map(function(file){return getMp4(file);})'を書いたのですか?もっとコーヒーが必要です。ありがとうございました。 (固定です) –

+0

あなたは大歓迎です:異質の関数ラッパーは常にバグです...:p – Alnitak

+0

@Alnitak:私もそうです。 :-) –

関連する問題