LoginSignup
5
6

More than 1 year has passed since last update.

【Django/async/await】JavaScriptでfetchなどの非同期処理を含んだループを順番に実行したい

Last updated at Posted at 2022-03-08

(編集履歴)

日付 内容
2022/3/9 @standard-software さんからのご指摘を受け、状況説明をより詳細にし、これに合わせてタイトルに文言を追加しました。

djangoを使った開発をしていて、「クライアント側からサーバー側にfetchなどでリクエストを送って、時間のかかる処理が終わるのを待ち、処理完了したら1サイクル終了」といった操作を、指定回数だけ順番に繰り返したい…こんな状況に出くわし、理解の浅い非同期処理を実装するのに右往左往してしまったので備忘録。
fetchを使う理由は、サーバーからのリクエストを受け取るときに、画面を再ロードしなくて済むようにしたいので、非同期処理としています。

簡便ですが開発環境は以下。
django: 3.1.4
OS: windows 10

最初にやらかした間違いコード

しょっぱな、「asyncを宣言時につけた関数はPromiseを返してくれる」という文言を見かけて、「じゃあasyncをつけた関数をawaitで待っていれば返り値が来るまで待ってくれるのか…?」と考え、こんなコードを書きました。(大枠だけ示しています)

間違いコード
let count = 3;  // 繰り返し回数

func(); // 実行

async function func() {
    // 非同期処理を含んだループ
    for (let i = 0; i < count; i++) {
        await myFunc();            // 処理の完了を待つ
        console.log(`${i+1}回目`); // コメント
    }
}

async function myFunc() {
    fetch('サーバーにリクエストするurl')
    .then((response, reject) => {
        // 時間のかかる処理を実行
        // 処理完了時に目印として「非同期処理終わり」を出力する
    });
}

やりたいことと気合は十分伝わってくるコードではあります(たぶん)。
出てきてほしい結果は、

期待する結果
非同期処理おわり
1回目
非同期処理おわり
2回目
非同期処理おわり
3回目

なわけですが、実際に実行してみると、

現実
1回目
2回目
3回目
非同期処理おわり
非同期処理おわり
非同期処理おわり

のように、ループ内のawait myFunc()はほぼ無視してループはどんどん進んでしまいました。

非同期処理をループさせる方法

というわけであれこれ調べた結果、最終的には以下のようにして非同期処理全体をnew Promiseとして返すことで、思い通りの動作を得ることができました。

// ※ myFuncの中身だけ変わっています。

let count = 3;  // 繰り返し回数

func(); // 実行

async function func() {
    // 非同期処理を含んだループ
    for (let i = 0; i < count; i++) {
        await myFunc();            // 処理の完了を待つ
        console.log(`${i+1}回目`); // コメント
    }
}

// 以下変更点
async function myFunc() {
    return new Promise((resolve) => {
        fetch('サーバーにリクエストするurl')
        .then((response, reject) => {
            // 時間のかかる処理を実行
            // 処理完了時に目印として「非同期処理終わり」を出力する
            resolve('返したいものがあれば返す');
        });
    });
}

参考

以下記事にお世話になりました。
async await の使い方

5
6
9

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6