シンプルな同期Node.jsプログラムをasync/awaitを使用する非同期バージョンに変換する方法を示す例をまとめます。通常のコールバックベースのバージョンから、2つのコールバックを使用するコールバック、通常(解決)の場合とエラー(拒否)の場合の2つの中間ステップから、約束につながるいくつかの中間ステップが必要です。ノードスタイルのコールバックを2つのコールバックに分割する
各バージョンのジョブが(すでに存在している可能性があり、それはファイルが含まれているかもしれない)空のフォルダコピーを作成し、フォルダ内のすべてのファイル( FILE2.TXT FILE1.TXTとと呼ばれる)をコピーすることですorigがあります。どこにでもエラーが発生した場合は、明示的にキャッチしてコンソールに出力し、プログラムをそれ以上続行しないでください。
通常のエラーファーストコールバックのバージョンは正常ですが、スプリットコールバックバージョンの問題が発生しました。 file2.txtのみをコピーしますが、file1.txtはコピーしません。
const fs = require('fs');
fs.exists = function(path, callback) {
fs.stat(path, (err, stats) => {
if (err) {
callback(null, false);
} else {
callback(null, true);
}
});
};
function splitCallback(f) {
return (...params) => {
reject = params[params.length - 2];
resolve = params[params.length - 1];
params = params.slice(0, params.length - 2);
f(...params, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
};
}
const sfs = {};
const functionNames = ['exists', 'readdir', 'unlink', 'mkdir', 'readFile', 'writeFile'];
for (const functionName of functionNames) {
sfs[functionName] = splitCallback(fs[functionName].bind(fs));
}
そして、これは、これらの機能を使用して、実際の例です:
function handleError(err) {
console.error(err);
}
function initCopyDirectory(callback) {
sfs.exists('copy', handleError, exists => {
if (exists) {
sfs.readdir('copy', handleError, filenames => {
let fileCount = filenames.length;
if (fileCount === 0) {
callback();
}
for (const filename of filenames) {
sfs.unlink(`copy/${filename}`, handleError,() => {
fileCount--;
if (fileCount === 0) {
callback();
}
});
}
});
} else {
sfs.mkdir('copy', handleError,() => callback);
}
});
}
function copyFiles() {
// sfs.readdir('orig', handleError, filenames => {
// for (const filename of filenames) {
// console.log(filename);
// sfs.readFile(`orig/${filename}`, handleError, data => {
// console.log('reading', filename);
// sfs.writeFile(`copy/${filename}`, data, handleError,() => {
// console.log('writing', filename);
// });
// });
// }
// });
sfs.readdir('orig', handleError, filenames => {
for (const filename of filenames) {
fs.readFile(`orig/${filename}`, (err, data) => {
if (err) {
handleError(err);
} else {
sfs.writeFile(`copy/${filename}`, data, handleError,() => {});
}
});
}
});
}
function main() {
initCopyDirectory(copyFiles);
}
main();
それがここに書かれているとして、それが正常に動作します(ここで
は、私はFS-機能を変換するために使用するコードですノードバージョン7.4.0 for Windowsを使用しています)。しかし、copyFiles関数でコメントを入れ替えると(readFileを変更すると)、1つのファイルだけがコピーされ、次の出力が得られます。file1.txt
file2.txt
reading file2.txt
writing file2.txt
writing file2.txt
問題点は何ですか?
これは私が最初に考えたことですが、私はここでも同じ結果が得られます。そして、[this](http://exploringjs.com/es6/ch_for-of.html#_iteration-variables-const-declarations-versus-var-declarations)によれば、私はconst宣言された変数の新しいバインディングをfor-ofループを繰り返します。 – Ignavia
@Ignavia「新鮮な綴り」はどういう意味ですか? constを使用しても、forループ内の非同期関数内のバインディングを保持できないという事実は変わりません。これは、常に非同期関数より速くなります – AllTheTime
少し変更された形式で簡単な例を使用します: 'const a = [1,2,3、 4,5,6,7,8,9,10]; for(var i of a){ setTimeout(function(){ console.log(i); }、100); } 'は出力として10回10を生成し、' const a = [1,2,3,4,5,6,7,8,9,10]です。 for(const i){ setTimeout(function(){ console.log(i); }、100); } 'は1から10までの数字を生成します。最初のコメントのリンクの下にはより良いフォーマットのバージョンがあります。 – Ignavia