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

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

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

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

非同期処理

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

Q&A

解決済

2回答

383閲覧

javascriptのpromiseでチェーン処理

uer03108

総合スコア194

JavaScript

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

非同期処理

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

0グッド

0クリップ

投稿2018/06/09 10:26

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

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

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

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

javascript

1 2/////////////////////////////////////////////////// 3// 4// onLoad 5// 6/////////////////////////////////////////////////// 7$(window).on('load',function(){ 8 9 /////////////////////////////////////////// 10 // 11 // 処理1 12 // 13 /////////////////////////////////////////// 14 var promise = new Promise(function(resolve, reject) { 15 16 //リクエスト配列 17 var aryRequest = []; 18 19 //データ数 20 var numData = 0; 21 22 //データ 23 var aryData = ["data1", "data2", "data3", "data4", "data5"]; 24 25 //データループ 26 aryData.forEach(function(data) { 27 28 // 29 window.setTimeout(() =>{ 30 31 //表示 32 console.log("shori1 " + numData + " " + data); 33 34 //登録 35 aryRequest.push("reqest_" + data); 36 37 //更新 38 numData++; 39 40 //終了 41 if(numData == aryData.length){ 42 resolve(aryRequest); 43 return false; //break; 44 } 45 46 }, 1); 47 }); 48 49 }); 50 51 52 /////////////////////////////////////////// 53 // 54 // 処理2 55 // 56 /////////////////////////////////////////// 57 promise.then(function(value) { 58 59 //リクエスト 60 var aryRequest = value; 61 62 //リクエスト数 63 var numRequest = 0; 64 65 //リクエストループ 66 aryRequest.forEach(function(request) { 67 68 // 69 window.setTimeout(() =>{ 70 71 //処理 72 console.log("shori2 " + numRequest + " " + aryRequest[numRequest]); 73 74 //更新 75 numRequest++; 76 77 //終了 78 if(numRequest == aryRequest.length){ 79 return false; //break; 80 } 81 82 }, 1); 83 }); 84 85 return true; 86 87 }).then(function(value) { 88 89 //表示 90 console.log("end"); 91 92 //プロセスエラー 93 }).catch(function (error) { 94 95 //表示 96 console.log("error"); 97 98 }); 99 100 101}); 102

処理結果

text

1 2shori1 0 data1 3shori1 1 data2 4shori1 2 data3 5shori1 3 data4 6shori1 4 data5 7end 8shori2 0 reqest_data1 9shori2 1 reqest_data2 10shori2 2 reqest_data3 11shori2 3 reqest_data4 12shori2 4 reqest_data5 13

 endが先に来る。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

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 10:44

sagami1991

総合スコア216

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2018/06/09 10:55

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

2018/06/09 15:38

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

2018/06/09 15:41 編集

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

2018/06/10 12:31

有難うございました。
uer03108

2018/06/11 09:36

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

2018/06/11 09:39

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

2018/06/11 11:07 編集

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

0

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

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

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

投稿2018/06/09 10:38

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uer03108

2018/06/10 12:31

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問