質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.52%

  • JavaScript

    16348questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • 非同期処理

    108questions

    非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

javascriptのpromiseでチェーン処理

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 211

uer03108

score 95

javasciptのpromiseでチェーン処理を行いたいのですが、順番通りになりませんでした。

・処理1(setTimeoutループ)
・処理2(setTimeoutループ)
・処理3(end)

の順番に処理をしたいのですが、処理2と処理3の順番が入れ替わりました。

仕様なのでしょうか。
promiseの中にpromiseを書いても良いのですが、それだとチェーンの意味が無い様な。

///////////////////////////////////////////////////
//
//  onLoad
//
///////////////////////////////////////////////////
$(window).on('load',function(){

    ///////////////////////////////////////////
    //
    //  処理1
    //
    ///////////////////////////////////////////
    var promise = new Promise(function(resolve, reject) {

      //リクエスト配列
      var aryRequest = [];

      //データ数
      var numData = 0;

      //データ
      var aryData = ["data1", "data2", "data3", "data4", "data5"];

      //データループ
      aryData.forEach(function(data) {

      //
      window.setTimeout(() =>{

        //表示
        console.log("shori1 " + numData + " " + data);

        //登録
        aryRequest.push("reqest_" + data);

        //更新
        numData++;

        //終了
        if(numData == aryData.length){
          resolve(aryRequest);
          return false;  //break;
        }

      }, 1);
      });

    });


    ///////////////////////////////////////////
    //
    //  処理2
    //
    ///////////////////////////////////////////
    promise.then(function(value) {

      //リクエスト
      var aryRequest = value;

      //リクエスト数
      var numRequest = 0;

      //リクエストループ
      aryRequest.forEach(function(request) {

      //
      window.setTimeout(() =>{

        //処理
        console.log("shori2 " + numRequest + " " + aryRequest[numRequest]);

        //更新
        numRequest++;

        //終了
        if(numRequest == aryRequest.length){
          return false;  //break;
        }

      }, 1);
      });

      return true;

    }).then(function(value) {

      //表示
      console.log("end");

    //プロセスエラー
    }).catch(function (error) {

      //表示
      console.log("error");

    });


});

処理結果

shori1 0 data1
shori1 1 data2
shori1 2 data3
shori1 3 data4
shori1 4 data5
end
shori2 0 reqest_data1
shori2 1 reqest_data2
shori2 2 reqest_data3
shori2 3 reqest_data4
shori2 4 reqest_data5


endが先に来る。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

then()...then()とつながるところが、Promiseオブジェクトを返していないので、待たずにendまで直行してしまいます。
以下のようにPromiseオブジェクトを返せば問題ありません。(めんどくさいでfunctionではなくes6のallow記述で関数をかいてます)

    promise.then(function(value) {
        var aryRequest = value;
        var numRequest = 0;
        return new Promise((resolve, reject) => {
            aryRequest.forEach(() => {
                window.setTimeout(() => {
                    console.log("shori2 " + numRequest + " " + aryRequest[numRequest]);
                    numRequest++;
                    if (numRequest === aryRequest.length) {
                        return resolve();
                    }
                }, 1);
            });
        });
    }).then(function (value) {
        console.log("end");
    })

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/09 19:55

    arrowで書くときは、「.then(value => new Promise((resolve, reject) => {」のように始めれば、必要以上にネストが深くなるのも避けられます。

    キャンセル

  • 2018/06/09 20:47

    たしカニ

    キャンセル

  • 2018/06/10 00:38

    有難うございました。
    試してみます。
    N個の非同期処理を順番に行う場合は、promiseもN個になってネストが1段ずつ深くなるという理解で宜しいでしょうか。

    キャンセル

  • 2018/06/10 00:41 編集

    いえ、ちがいます
    こんな感じになってネストは別に深くなりません
    var promise = new Promise(...処理1);
    promise.then(() => new Promise(...処理2))
    .then(() => new Promise(..処理3))
    .then(() => new Promise(..処理4))
    .then(() => new Promise(...処理5))

    キャンセル

  • 2018/06/10 21:31

    有難うございました。

    キャンセル

  • 2018/06/11 18:36

    setTimeoutを使うと表示が上手くいきませんでした。
    setIntervalで対応いたしました。

    キャンセル

  • 2018/06/11 18:39

    setIntervalはn秒間隔である関数を実行するのでまた異なる意味合いになってしまいます

    キャンセル

  • 2018/06/11 20:05 編集

    確かに、仰る通りですね。

    キャンセル

+2

Promise.prototype.then(関数1).then(関数2)で、関数2の実行のタイミングは、関数1返り値に依存します。

  • 関数1Promiseを返した場合…このPromiseresolvedとなった段階で関数2が実行される
  • それ以外の場合…関数2は、関数1の実行直後に実行される

ということで、非同期処理を連鎖させたい場合には、「promiseの中にpromiseを書」くしかない「仕様」です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/10 21:31

    理解致しました。
    return value;
    が呼ばれた時点で次の関数が実行ですね。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • JavaScript

    16348questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • 非同期処理

    108questions

    非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。