【先端の冷たい知識】JSのベストプラクティス(1)

1830 ワード

Programs are meant to be read by humans and only incidentally for computers to execute.
—— Donald Knuth
今日、微信グループで質問がありました.
repeat()=>{console.log('1')},5,2000)が2秒ごとに印刷されるように、関数を実装するにはどうすればいいですか.合計5回ですか.
この問題はもちろん難しくありません.タイマーを使えばいいです.基本的にJSを書くことができる学生はこの問題を解決することができます.ES 2017までは、実装方法もいろいろありましたが、今では9102年になりましたので、私が実装するなら、基本的に次のコードを書くのをためらうことはありません.
function wait(millisecond) {
  return new Promise((resolve) => {
    setTimeout(resolve, millisecond);
  });
}
async function repeat(task, count = 1, millisecond = 0) {
  while(count--) {
    await wait(millisecond);
    task();
  }
}
どうしてこう書いたのですか.このコード構造は極めて簡単なので、whileサイクルは基本的にプログラム開発を学んだ初心者でも理解でき、async/awaitの意味(実際には推測できる)を理解すれば、コードの意味を徹底的に理解することができます.
while(count--) {
    await wait(millisecond);
    task();
  }
ループcount回、wait数ミリ秒ごとに、このコードロジックはコメントを必要としないほど簡単です.
使用も便利です.それ自体がasyncの関数でpromiseを返すため、実行が完了した後に他のタスクを実行する必要がある場合は、async functionに配置しawaitを加えるだけです.
(async function() {
  await repeat(taskA, 5, 2000);
  taskB();
 }());
逆に、タスクを同期して実行する場合はawaitを削除するだけです.
repeat(taskA, 5, 2000);
taskB();
A、Bを何度も繰り返し、A、Bを順番に実行したい場合は、次のようにします.
await repeat(taskA, 5, 2000);
await repeat(taskB, 5, 2000);
A、Bを何度も繰り返し、並列に実行したい場合は、次のようにします.
await Promise.all([repeat(taskA, 5, 2000), repeat(taskB, 5, 2000)])
taskA、taskBも非同期方法であることを望む場合は、repeat実装を少し修正することができます.
async function repeat(task, count = 1, millisecond = 0) {
  while(count--) {
    await wait(millisecond);
    await task();
  }
}
要するに、コードは人に読ませるもので、ES 2017以降、JavaScriptはasync functionをサポートしています.非同期操作を処理するときは、async functionを使って、簡潔で、読みやすく、理解しやすいコードを書くことができます.
async/awaitのベストプラクティスについては、issueで議論することを歓迎します.