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

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

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

Cordovaは様々なデバイスで使うことができるオープンソースなモバイル用開発プラットフォームです。開発者に各デバイスの元のプラットフォームで開発する必要をなくし、HTML・JavaScript・CSSなどの一般的なウェブのテクノロジーを使ってすべてのデバイスで展開することができるモバイルのアプリケーションを生成することを可能にします。

JavaScript

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Monaca

「Monaca」はiOS、Android、Windows向けのアプリ開発に対応した、Cordovaベースのモバイルアプリ開発プラットフォームです。HTML5、JavaScriptといったWeb標準技術を用いてモバイルアプリ開発を行うことができます。

Q&A

解決済

1回答

2156閲覧

JavaScriptの繰り返し処理(for文)がうまくいきません

agepan

総合スコア66

Cordova

Cordovaは様々なデバイスで使うことができるオープンソースなモバイル用開発プラットフォームです。開発者に各デバイスの元のプラットフォームで開発する必要をなくし、HTML・JavaScript・CSSなどの一般的なウェブのテクノロジーを使ってすべてのデバイスで展開することができるモバイルのアプリケーションを生成することを可能にします。

JavaScript

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Monaca

「Monaca」はiOS、Android、Windows向けのアプリ開発に対応した、Cordovaベースのモバイルアプリ開発プラットフォームです。HTML5、JavaScriptといったWeb標準技術を用いてモバイルアプリ開発を行うことができます。

0グッド

0クリップ

投稿2017/12/06 04:47

編集2017/12/06 04:47

現在下記のようなコードで、特定のフォルダの中にあるファイルをfor文を用いて取得・HTML上にフォルダ名を表示しようとしています。

特定のフォルダの名前はfolderListの配列にある「りんご」と「みかん」の2つです。
このコードを動かしてみると画面上には「みかん」「みかん」と、「りんご」が表示されずに「みかん」が2個表示されてしまいます。

繰り返し処理の変数iを調べるため、コード内の2箇所にアラートを付けて(「最初のアラート」と「2つ目のアラート」)確認してみました。すると画面に出た順序と内容は以下のようになりました。

(1)「最初のアラート0」
(2)「最初のアラート1」
(3)「2つ目のアラート1」
(4)「2つ目のアラート1」

この順序と動きを以下のようになるようにしたいのですが、どのようにコードを書き直せば良いでしょうか。よろしくお願いいたします。

(1)「最初のアラート0」
(2)「2つ目のアラート0」
(3)「最初のアラート1」
(4)「2つ目のアラート1」

JavaScript

1var folderList = ['りんご', 'みかん']; 2localStorage.setItem('folderList', folderList); 3 4for (var i = 0; i < folderList.length; i++){ 5 6 alert('最初のアラート' + i); 7 sessionStorage.setItem('i', i); // 繰り返しカウントを保存 8 9 var fileName = 'file.txt'; 10 var folderUrl = cordova.file.documentsDirectory + folderList[i] + '/'; 11 var folderList = localStorage.getItem('folderList'); 12 13 window.resolveLocalFileSystemURL( folderUrl , 14 function getDirectoryEntry( directoryEntry ) { 15 directoryEntry.getFile( fileName, null, 16 function readFile( fileEntry ) { 17 fileEntry.file( 18 function( file ) { 19 var reader = new FileReader(); 20 reader.onloadend = function() { 21 var settings = this.result; 22 settings = JSON.parse(result); 23 24 var persistentUrl = localStorage.getItem('persistentUrl'); 25 var folderList = localStorage.getItem('folderList'); 26 27 var i = sessionStorage.getItem('i'); 28 i = Number(i); 29 alert('2つ目のアラート' + i); 30 31 $('#div').append( 32 '<p>' + folderList[i] + '</p>' 33 ); 34 35 }; 36 reader.readAsText(file); 37 }, 38 function fail(e) { 39 // エラー処理 40 } 41 ); 42 }, 43 function fail(e) { 44 // エラー処理 45 } 46 ); 47 }, 48 function fail(e) { 49 // エラー処理 50 } 51 ); 52 53} 54

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

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

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

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

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

guest

回答1

0

ベストアンサー

非同期処理をループの中で素朴にやろうとするとどうしてもそういうことになると思います。

javascript

1for (i = 0; i < N; i++) { 2 var param = ...; 3 // 非同期処理起動 4 startAsync(param, function () { 5 // 非同期処理終了時処理 6 $(...).append(...); 7 } 8}

一般にこうかくとstartAsyncは並行して一斉に始まってしまい、完了した順番に終了時処理が起動されてしまいます。一般にコールバックを用いる前提で非同期処理を順番にやるには、次のようにコールバックをネストさせる方法(所謂コールバック地獄)を取らざるを得ないのですが、いくつの非同期処理があるかわからない現在のforループをこのように書き換えるのは現実的ではないと思います。

javaascript

1startAsync1(param1, function () { 2 // 1番目の完了処理 3 ... 4 // 2番目の開始 5 startAsync2(param2, function () { 6 // 2番目の完了処理 7 ... 8 // 3番目の開始 9 startAsync3(param3, function () { 10 ... 11 } 12 } 13}

そこでfor文を生かし任意の回数の非同期処理を順番に実行するアイデアとしては例えば次のようにする手があると思います。

javascript

1var tasks = []; 2for (i = 0; i < N; i++) { 3 // 非同期処理を行う関数を一旦配列へ用意する 4 tasks.push(function (i) { 5 var param = ...; 6 // i番目の非同期処理の開始 7 startAsync(param, function (result) { 8 // i番目の非同期処理の完了時処理 9 $(...).append(...); 10 // i+1番目の非同期処理を起動 11 var next = tasks.shift() 12 if (next) next(i + 1); 13 } 14 }); 15} 16var first = tasks.shift(); 17if (first) first(0); // 最初の非同期処理開始 18// この時点ではまだどの非同期処理も終わっていないことに注意

上記はループ毎に唯一の非同期処理しか動かしていませんが、実際はいくつかネストした非同期処理をループ毎にやっておられるようなので、もう少し複雑になると思います。

ES2015のasync/awaitや他のフレームワークならもっと違う書き方もできそうですが、タグに記載されたものに限定し比較的平易な方法と思ったのでコールバックを用いた例をコメントしてみました。

投稿2017/12/06 06:13

KSwordOfHaste

総合スコア18392

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

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

agepan

2017/12/06 07:06

ご回答ありがとうございました! 仕組みについて大変よく勉強になりました。お教え頂いたコードを自分なりにかみ砕きまして、非同期処理が1回完了するごとにそのカウントをsessionStorageに保存し、if文でフォルダ数とそのカウントが同じになるまで自分自身の関数を繰り返し実行させるコードにしてみたところ、理想的な動きをするようになりました。 ありがとうございました!
KSwordOfHaste

2017/12/06 07:31

なるほどそういう方法もありますね!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問