1. ホーム
  2. javascript

[解決済み] 非同期関数+await+setTimeoutの組合せ

2022-03-18 02:26:18

質問

私は新しい非同期機能を使おうとしています。私の問題を解決することが、将来的に他の人の役に立つことを願っています。これは私のコードで、動作しています。

  async function asyncGenerator() {
    // other code
    while (goOn) {
      // other code
      var fileList = await listFiles(nextPageToken);
      var parents = await requestParents(fileList);
      // other code
    }
    // other code
  }

  function listFiles(token) {
    return gapi.client.drive.files.list({
      'maxResults': sizeResults,
      'pageToken': token,
      'q': query
    });
  }

問題は、私のwhileループの実行が速すぎて、スクリプトがgoogle APIに毎秒多くのリクエストを送信していることです。そこで、リクエストを遅延させるスリープ関数を作りたいと思います。この関数を使えば、他のリクエストも遅らせることができます。もし、リクエストを遅延させる他の方法があれば、教えてください。

とにかく、これが私の新しいコードなのですが、うまくいきません。リクエストの応答は、setTimeout内の匿名async関数に返されますが、私はちょうど私が最初のasyncGenerator関数に対応するsleep関数に応答を返すことができる方法を知っています。

  async function asyncGenerator() {
    // other code
    while (goOn) {
      // other code
      var fileList = await sleep(listFiles, nextPageToken);
      var parents = await requestParents(fileList);
      // other code
    }
    // other code
  }

  function listFiles(token) {
    return gapi.client.drive.files.list({
      'maxResults': sizeResults,
      'pageToken': token,
      'q': query
    });
  }

  async function sleep(fn, par) {
    return await setTimeout(async function() {
      await fn(par);
    }, 3000, fn, par);
  }

私はすでにいくつかのオプションを試してみました:グローバル変数に応答を格納し、スリープ関数からそれを返す、匿名関数内でコールバック、などです。

どうすればいいですか?

あなたの sleep 関数が機能しないのは setTimeout になりうるプロミスを返さない(まだ?)のです。 await を作成しました。手動でプロミス化する必要があります。

function timeout(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
async function sleep(fn, ...args) {
    await timeout(3000);
    return fn(...args);
}

ループを遅くするために、おそらく sleep 関数は、このようにコールバックを受け取り、それをディファレンディングします。おすすめは

while (goOn) {
  // other code
  var [parents] = await Promise.all([
      listFiles(nextPageToken).then(requestParents),
      timeout(5000)
  ]);
  // other code
}

を計算させることができます。 parents は最低でも5秒かかる。