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

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

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

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

Q&A

解決済

4回答

9361閲覧

javascriptのループ処理の順番がめちゃくちゃ

ckaposndbbba

総合スコア210

JavaScript

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

0グッド

2クリップ

投稿2015/07/27 10:08

編集2015/07/27 11:00

こんにちは。
javascriptであるものを作っていて、その中にループ処理があるのですが、ループする順番がめちゃくちゃなんです。
forでもwhileでもダメです。25回ループしたいです。
コードは下記。

xhtml

1<ul class="result"></ul>

javascript

1// while 2var i = 1; 3while (i < 26){ 4 $('.result').append('<li>' + i + '</li>'); 5 i++; 6} 7 8//for 9for (var i = 1; i < 26; i++) { 10 $('.result').append('<li>' + i + '</li>'); 11} 12 13//どっちもダメ

結果がこうなります。

1 2 3 4 5 6 7 8 10 9 11 12 16 15 14 17 13 18 19 24 22 21 23 20 25

ところどころ順番がメチャクチャになっています。
あと、これ、全部こうなるのではなく、リロードしたら毎回順番が変わります。
そうじゃなくて、「1・2・3・4・5・6・7・・」と、順番通りに動かしたいです。
どうすればいいのでしょうか?
仕様なのでしょうか?解決策やサンプルコードなど提示していただければうれしいです。
よろしくお願いします。

**補足**
めちゃくちゃなコードですが、javascriptの全体の主なコードを貼り付けます。
確認していただけると幸いです。
ちなみに、データベースに接続するPHPと通信して、クイズアプリのようなものを作っています。
console.logや$(function(){など、要らない部分は削除しているので、必要な部分だけとなります。

javascript

1function mark_question (id, answer, while_i) { 2 var URI = 'api.php'; 3 var dataURI = 'id=' + id + '&answer=' + answer; 4 if (answer === undefined) { 5 answer = '5'; 6 } 7 $.ajax({ 8 type: 'GET', 9 url: URI, 10 dataType: 'json', 11 data: dataURI, 12 success: function(json){ 13 console.log('success'); 14 if(json[detail] == 'true') { 15 $('#result_detail:last-child').append('<li>' + while_i + '</li>'); 16 } else { 17 $('#result_detail:last-child').append('<li>' + while_i + '</li>'); 18 } 19 }, 20 error:function(json){ 21 console.log('error'); 22 } 23 }); 24} 25//---------------- 26for (var i = 1; i < 26; i++) { 27 var id = $('.c-' + i).attr('data-id'); 28 var answer = $('.c-' + i).attr('data-answer'); 29 mark_question(id, answer, i); 30}

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

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

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

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

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

guest

回答4

0

ベストアンサー

こんにちは。

検証のため、以下の2つのHTMLを作成しました。

(1) http://www.gattolibero.sakura.ne.jp/teratail/q13514-for.html

(2) http://www.gattolibero.sakura.ne.jp/teratail/q13514-while.html

上記を表示させると分かるとおり、問題のズレは生じていないです。

なので、問題解決のために、ループの中のAJAXも含む、HTMLと
javascriptのコード全体を追記して頂ければと思います。


追記1

AJAXを行っているコードをざっと読みました。

forループの中で、たとえば
mark_question(id, answer, 1);
mark_question(id, answer, 2);
の2つが、この順で呼ばれますが、それぞれの中で行っているAJAX通信での
レスポンスが、この順で返ってくるとは限りません。
したがって、
mark_question(id, answer, 2);
でのAJAXのレスポンスが先に返ってきて処理されたら、作られる
リストアイテムは
<li>2</li>
<li>1</li>
の順になります。


追記2

ちょっと応急的な手法になるかと思いますが、
こんな方法を考えてみました。

・APIを呼び出す直前に、内容が空の25個の<li>を作成する。

・その後、ループでAPIを呼び、呼び出し回数に応じた位置の<li>の内容を書き換える。

以下サンプルコードになります。

q13514-improved.html

javascript

1<!DOCTYPE html> 2<html> 3<head> 4<meta charset="UTF-8"> 5<title>teratail/q13514-improved</title> 6<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script> 7<script> 8function call_api(n) { 9 $.ajax({ 10 type: 'GET', 11 url: 'api.php', 12 dataType: 'json', 13 success: function(json){ 14 console.log("ok:" + n ); 15 $('.result li:nth-child(' + n + ')').text(n).css({display: 'block'}); 16 } 17 }); 18} 19 20function make_items() 21{ 22 // まず、内容が空のリストアイテムを25個作成 23 for (var i = 1; i < 26; i ++) { 24 $('.result').append($('<li>').css({display: 'none'})); 25 } 26 27 // 25 回 AJAX を行い、回数に応じた位置の li の内容を書き換える。 28 for (var i = 1; i < 26; i ++) { 29 call_api(i); 30 } 31} 32</script> 33</head> 34<body> 35 <ul class="result"></ul> 36 <hr /> 37 <a href="" onclick="make_items(); return(false);">click me !</a> 38</body> 39</html>

api.php はとりあえず以下のように、空のJSONを返すだけのものです。

api.php

php

1<?php 2header("Content-Type: application/json; charset=utf-8"); 3 4echo '{}';

上記のq13514-improved.htmlとapi.phpを作成して以下に上げました。

http://www.gattolibero.sakura.ne.jp/teratail/q13514-improved.html

http://www.gattolibero.sakura.ne.jp/teratail/api.php

click me ! をクリックすると、AJAXのレスポンスの順番が、
ループの順にならなくても、リストの表示としては順番に
なります。

投稿2015/07/27 10:50

編集2015/07/28 19:09
jun68ykt

総合スコア9058

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

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

ckaposndbbba

2015/07/27 10:56

わざわざありがとうございます! では、補足としてソースを記入します。よろしくお願いします。
jun68ykt

2015/07/27 12:21

ちょっと対症療法的というか、とりあえずの応急措置っぽい方法ですが、対策を考えてみました。追記2 をご覧ください。何か参考になれば幸いです。
ckaposndbbba

2015/07/28 12:04

ありがとうございます!提示された方法を真似てやってみたら、成功しました! ありがとうございましたm(_ _)m
jun68ykt

2015/07/28 18:45

どういたしまして。解決されたようで、よかったです!
guest

0

もしかして本当は次のように中で ajax で処理してコールバックの中でリストを追加しているのでしょうか?

for (var i = 1; i < 26; i++) { (function(){ var j = i; $.ajax('?', {}).then(function(){ $('.result').append('<li>' + j + '</li>'); }); }()) }

この場合、ajax が直列に実行されるようにするか、

var defer = $.Deferred().resolve(); for (var i = 1; i < 26; i++) { (function(){ var j = i; defer = defer.then(function(){ return $.ajax('?', {}).then(function(){ $('.result').append('<li>' + j + '</li>'); }); }) }()) }

非同期処理の待ち合わせをする必要があります。

var list = []; for (var i = 1; i < 26; i++) { (function(){ var j = i; var x = $.ajax('?', {}).then(function(){ return j; }); list.push(x); }()) } $.when.apply(null, list).then(function(){ $.each(arguments, function(i, j){ $('.result').append('<li>' + j + '</li>'); }); })

ひとまず、ajax も絡めた実際のコードを質問に追記すると良いかと思います。


$.ajax の引数の success は使わずに $.ajax の戻り値の then で処理するようにします。

then に渡すコールバック関数の引数は・・ success に渡すコールバック関数の引数とは違った気がするのですが、パッと思い出せないので調べてください。

mark_question 関数は then の戻り値を返します。

これらは関数の呼び出し元で Promise を利用するためです。

関数の呼び出し側のコードで Promise を直列につなげます。

かなり簡略化しましたが、下記のような感じです。

javascript

1function mark_question (while_i) { 2 return $.ajax({ 3 type: 'get', 4 url: '?' 5 }) 6 .then(function(){ 7 $('.result').append('<li>' + while_i + '</li>'); 8 }) 9} 10 11var defer = $.Deferred().resolve(); 12 13for (var i = 1; i < 26; i++) { 14 (function(){ 15 var j = i; 16 defer = defer.then(function(){ 17 return mark_question(j) 18 }); 19 }()) 20}

もし、これが何をやっているのかわからないなら、jQuery と Deferred(Promise) について学ぶ必要があります。

なお、これは↑であげた2番目のコード例です(ajax が直列に実行されるようにする)。
3番目の「非同期処理の待ち合わせ」でも、頑張ればできます。

投稿2015/07/27 10:53

編集2015/07/27 11:11
ngyuki

総合スコア4514

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

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

ckaposndbbba

2015/07/27 10:56

ありがとうございます! では、補足としてソースを記入します。よろしくお願いします。
guest

0

javascript

1for (var i = 1; i < 26; i++) { 2 $('.result:last-child').append('<li>' + i + '</li>'); 3}

これでどうでしょうか。

投稿2015/07/27 10:20

yu-ri

総合スコア634

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

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

ckaposndbbba

2015/07/27 10:29

ありがとうございます! 早速、提示された方法を試してみたのですが、やはりうまく行きませんでした・・><
yu-ri

2015/07/27 10:43 編集

単純にループだけなら上記ソースで間違いなく動くと思うのですが、NIA様へのコメントを拝見するとAjax通信が割り込んでいるそうで。 非同期通信ですと応答順に表示されるはずですから、それでずれてるんだと思います。 同期通信にすれば解決するかと思いますが、いかがでしょうか。
ckaposndbbba

2015/07/27 10:46

そうなんですか。 では、(めちゃくちゃなコードですが、すみません)コードを一部貼り付けます>< 長くなるかもしれませんがどうぞ。 function mark_question (id, answer, while_i) { var URI = 'api.php'; var dataURI = 'id=' + id + '&answer=' + answer; if (answer === undefined) { answer = '5'; } $.ajax({ type: 'GET', url: URI, dataType: 'json', data: dataURI, success: function(json){ console.log('success'); if(json[detail] == 'true') { $('#result_detail:last-child').append('<li>' + while_i + '</li>'); } else { $('#result_detail:last-child').append('<li>' + while_i + '</li>'); } }, error:function(json){ console.log('error'); } }); } ---------------- for (var i = 1; i < 26; i++) { var id = $('.c-' + i).attr('data-id'); var answer = $('.c-' + i).attr('data-answer'); mark_question(id, answer, i); }
yu-ri

2015/07/27 11:00

ajaxの引数に、 async:false を追加すればひとまず目的は達成できるかと思いますが、処理待ちで画面がフリーズするかもしれないのでお勧めはできません(汗 他の方のご回答を参考にして、一番いい方法を使ってください!
guest

0

JQuery は基本非同期なので、タグ追加程度ならJSでやった方が良いと思いますよ。

JQuery でやるならば下記のようにタグを作ってから追加すればよいかと。

Javascript

1// while 2var i = 1; 3var tags = ''; 4 5while ( i < 26 ) 6{ 7 tags += '<li>' + i + '</li>'; 8 i++; 9} 10 11$('.result').append(tags); 12 13tags = ''; 14//for 15for( var i = 1; i < 26; i++ ) 16{ 17 tags += '<li>' + i + '</li>'; 18} 19$('.result').append(tags );

投稿2015/07/27 10:18

NIA

総合スコア181

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

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

ckaposndbbba

2015/07/27 10:29

ありがとうございます。 実は、ループ処理の中の、要らない部分は削除して書いています。 本当は、ループ処理の中に、Ajax通信の処理が含まれているのです(>_<) そのような場合?はどうすればいいでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問