[解決済み] 約束事を次々と解決していく(=順番に解決していく)?
2022-03-15 11:40:01
質問
ファイルの配列をシリアル/シーケンシャルに読み取る次のコードを考えてください。
readFiles
はプロミスを返し、それはすべてのファイルが順番に読み込まれたときにのみ解決される。
var readFile = function(file) {
... // Returns a promise.
};
var readFiles = function(files) {
return new Promise((resolve, reject) => {
var readSequential = function(index) {
if (index >= files.length) {
resolve();
} else {
readFile(files[index]).then(function() {
readSequential(index + 1);
}).catch(reject);
}
};
readSequential(0); // Start with the first file!
});
};
上記のコードは動作しますが、私は物事が順次発生するために再帰を行わなければならないのが好きではありません。このコードをもっとシンプルに書き直す方法はないでしょうか。
readSequential
関数を使用できますか?
元々、私は
Promise.all
が、そのためにすべての
readFile
の呼び出しが同時に発生することになり、これは
ない
ということです。
var readFiles = function(files) {
return Promise.all(files.map(function(file) {
return readFile(file);
}));
};
解決方法は?
2017年のアップデート : 環境がサポートしていれば、非同期関数を使用します。
async function readFiles(files) {
for(const file of files) {
await readFile(file);
}
};
必要であれば、非同期ジェネレータを使用して、必要な時までファイルの読み込みを延期することができます (環境がサポートしている場合)。
async function* readFiles(files) {
for(const file of files) {
yield await readFile(file);
}
};
更新:考え直した結果、代わりにforループを使うかもしれません。
var readFiles = function(files) {
var p = Promise.resolve(); // Q() in q
files.forEach(file =>
p = p.then(() => readFile(file));
);
return p;
};
あるいはもっとコンパクトに、reduceで。
var readFiles = function(files) {
return files.reduce((p, file) => {
return p.then(() => readFile(file));
}, Promise.resolve()); // initial
};
他のプロミスライブラリ(whenやBluebirdなど)には、このためのユーティリティメソッドがあります。
例えば、Bluebirdなら。
var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs"));
var readAll = Promise.resolve(files).map(fs.readFileAsync,{concurrency: 1 });
// if the order matters, you can use Promise.each instead and omit concurrency param
readAll.then(function(allFileContents){
// do stuff to read files.
});
特に理由はないのですが ない は、今日、非同期awaitを使用します。
関連
-
要素ツリー制御によるvueTreeテーブル
-
Vueの要素ツリーコントロールに破線を追加する説明
-
JavaScriptのクロージャの説明
-
Vueの一般的な組み込みディレクティブの説明
-
[解決済み】Uncaught SyntaxError: JSONの位置0に予期しないトークンuがあります。
-
[解決済み】 env: node: macにそのようなファイルやディレクトリはありません
-
JavaScriptのStringに関する共通メソッド
-
[解決済み] JavaScriptでライブラリを使わずに、他の要素の後に要素を挿入するにはどうしたらいいですか?
-
[解決済み] 早期解決・早期却下の後、戻る必要はありますか?
-
[解決済み] Node JSのPromise.allとforEach
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
JSクロスドメインソリューション リアクト構成 リバースプロキシ
-
JavaScriptの配列共通メソッド解説
-
Vueのフィルタの説明
-
[解決済み] Error : 未定義のプロパティ 'map' を読み取ることができません。
-
[解決済み】Uncaught SyntaxError: JSONの位置0に予期しないトークンuがあります。
-
[解決済み】JavaScriptの配列でforEachが関数でない不具合
-
[解決済み】TypeError: Router.use() はミドルウェアの関数を要求しているが、Object を取得した。
-
[解決済み】「X-Frame-Options」を「SAMEORIGIN」に設定したため、フレームでの表示を拒否された。
-
モジュールのビルドに失敗しました。Error: ENOENT: no such file or directory, scandir 'D:\.... \node_modules
-
[解決済み] JavaScript ES6 promise for loop [重複]について