(JS)BelloperのモダンJavaScript:Promise


Promise


「プロセス」はES 6に導入された機能で、非同期操作をより容易にすることができます.以前は非同期タスクを処理する際にコールバック関数を用いて処理する必要があったが,コールバック関数を用いて処理すると,非同期タスクが多くなるとコードが乱雑になりやすい.
デジタルnをパラメータとして1回、毎秒1回の出力を5回加算する動作をsettimeoutとして実現し、数回のコールバックのない連続性を見ることができる.(callback地獄)
function increaseAndPrint(n, callback) {
  setTimeout(() => {
    const increased = n + 1;
    console.log(increased);
    if (callback) {
      callback(increased);
    }
  }, 1000);
}

increaseAndPrint(0, n => {
  increaseAndPrint(n, n => {
    increaseAndPrint(n, n => {
      increaseAndPrint(n, n => {
        increaseAndPrint(n, n => {
          console.log('끝!');
        });
      });
    });
  });
});
この読みにくいコードをcallback hellと呼びます.
非同期処理が必要なことが多ければ多いほど,コードが深まる現象を防ぐことができる.

Promiseの作成

const MyPromise = new Promise((resolve, reject) => {
  // 구현 ...
})
Promiseは成功しても失敗してもいいです.成功したときはresolve、失敗したときはresoldを呼ぶ.
const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1);
  }, 1000);
});

myPromise.then(n => {
  console.log(n);
});
resolveを呼び出すときに値をパラメータとして使用する場合は、操作が完了した後にこの値を使用できます.仕事が終わってから他の仕事をする必要がある場合は、Promiseの後に.then(...)を付けて使用できます.

1秒に設定して失敗

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(new Error());
  });
  
  myPromise
  	.then(n => {
      console.log(n);
  	})
  	.catch(error => {
      console.log(error);
  });
失敗した場合は、rejectを使用して、失敗したときに実行する操作を.catchで設定できます.
function increaseAndPrint(n) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const value = n + 1;
      if (value === 5) {
        const error = new Error();
        error.name = 'ValueIsFiveError';
        reject(error);
        return;
      }
      console.log(value);
      resolve(value);
    }, 1000);
  });
}

increaseAndPrint(0).then((n) => {
  console.log('result: ', n);
})

Promiseのプロパティで、次に内部に入った関数でPromiseを返すと、連続して使用できます.
function increaseAndPrint(n) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const value = n + 1;
      if (value === 5) {
        const error = new Error();
        error.name = 'ValueIsFiveError';
        reject(error);
        return;
      }
      console.log(value);
      resolve(value);
    }, 1000);
  });
}

increaseAndPrint(0)
  .then(n => {
    return increaseAndPrint(n);
  })
  .then(n => {
    return increaseAndPrint(n);
  })
  .then(n => {
    return increaseAndPrint(n);
  })
  .then(n => {
    return increaseAndPrint(n);
  })
  .then(n => {
    return increaseAndPrint(n);
  })
  .catch(e => P
    console.error(e);
  });

上のコードは以下のように整理できます.
function increaseAndPrint(n) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const value = n + 1;
      if (value === 5) {
        const error = new Error();
        reject(error);
        return;
      }
      console.log(value);
      resolve(value);
    }, 1000);
  });
}

increaseAndPrint(0)
  .then(increaseAndPrint)
  .then(increaseAndPrint)
  .then(increaseAndPrint)
  .then(increaseAndPrint)
  .then(increaseAndPrint)
  .catch(e => {
    console.error(e);
  });
Promiseを使用すると、非同期操作の数が増えてもコードの深さは深くなりません.
でもPromiseには不便なところもあります.エラーをキャプチャする場合,何回目に発生したかを検出することは困難であり,特定の条件に従って分岐することも困難であり,特定の値を共有しながらタスクを処理することも困難である.async/awaitを使用すると、これらの問題を解決できます.