9915


複数URLの取得結果をまとめた配列にしたいのですが、下記のコードでは結果がNULLになってしまします。  
ログではtitleは取れている形跡はみられますが、配列をNULL要素で作った後にWebから結果を取得しているように見えます。

[code]

    <!DOCTYPE html>
    <html lang="ja">
    <head>
      <meta charset="utf-8">
      <title>demo</title>
    </head>
    <body>
    <div id="result"></div>
    
    <script src="../lib/jquery-1.11.3.min.js"></script>
    <script type="text/javascript">
    
      var urls = [
        "http://localhost:8080/books/1.json",
        "http://localhost:8080/books/2.json",
        "http://localhost:8080/books/3.json",
      ];
    
      var getTitle = function (url) {
        $.get(url,
            function (data) {
              console.log("title:" + data.title);
              return {
                url: url,
                title: data.title
              }
            }
        );
      };
    
      var results = urls.map(getTitle);
      console.log("results: " + JSON.stringify(results));
      $("#result").text(JSON.stringify(results));
    
    </script>
    </body>
    </html>
[/code]

結果ログ  
  
results: [null,null,null]  
title:t12  
title:t1  
title:t13  

results: [{url:"http://〜/1.json", title: t1},{ (略) },{ (略) }]  
のような配列を取得するにはどうすれば良いでしょうか？

よろしくお願いいたします。


CC BY-SA 3.0
2015-05-07T14:39:13.333
9910
2015-05-07T16:09:55.357
9640
question
javascript jquery ajax
複数APIの結果をまとめた配列を取得したい。（非同期）


`$.get()` に渡している匿名関数を外に出してみます。

[code]

    var onJsonGetComplete = function (data) {
        console.log("title:" + data.title);
        return {
            url: url,
            title: data.title
        }
    };
    
    var getTitle = function (url) {
        $.get(url, onJsonGetComplete);
    };
    
    var results = urls.map(getTitle);
    
[/code]

`getTitle` から `return {...}` をしたかったのだと思いますが、実際には `$.get()` に渡した匿名関数から return
しています。そして `getTitle` では何も return していませんから、 map の結果も全て null 、というわけです。

さて、それぞれが非同期に取得した結果をどこかに溜め込んでおいて、全部そろったところで目的の処理をする、という方法が考えられます。例えば・・・

[code]

    var urls = [
        "https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js",
        "https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js",
        "https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"
    ];
    
    var results = urls.map(function() { return null; });
    
    urls.forEach(function (url, i) {
        $.get(url,
            function (data) {
                results[i] = {
                    url: url,
                    len: data.length
                };
                
                // 全て読み込めたかチェック
                var completed = results.every(function(res) {
                    return res !== null;
                });
                if(completed) {
                    $("body").text(JSON.stringify(results));
                }
            });
    });
[/code]

[code]

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
[/code]

Deferredと `$.when()` を使うと短く書けますが、配列での入出力ができないのでapplyやargumentsが必要でした。

[code]

    var urls = [
        "https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js",
        "https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js",
        "https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"
    ];
    
    var dfds = urls.map(function(url) {
      return $.get(url);
    });
    
    $.when.apply($, dfds).done(function(){
        var args = arguments;
        var results = urls.map(function(url, i) {
            var res = args[i][0];
            return {
                url: url,
                len: res.length
            };
        });
        $("body").text(JSON.stringify(results));
    });
[/code]

[code]

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
[/code]

ここまでに挙げたコードもシンプルとは言い難いですし、一部の取得に失敗したケースなどを考慮するとさらにややこしくなります。順番に取得したり、それぞれ独立して画面等への反映まで行うようにした方が、簡単に書けるのではないでしょうか。


CC BY-SA 3.0
2015-05-07T16:09:55.357
9915
2015-05-07T16:09:55.357
8000
9910
answer