0

タイトルを指定して、ウィキペディアのページにリンクされているすべての記事の配列を返すことになっている JavaScript の関数があります。

ここにあります:

function getLinksFrom(title, returnArray, plcontinue) {
  var url = 'http://en.wikipedia.org/w/api.php?action=query&prop=links&titles=' + title + '&format=json&pllimit=500&plnamespace=0&callback=?';
  if (!returnArray) {
      returnArray = [];
  }
  if (!plcontinue) {
    plcontinue = '';
  }
  if (returnArray.length === 0 || plcontinue !== '') {
      if (plcontinue !== '') {
          url = 'http://en.wikipedia.org/w/api.php?action=query&prop=links&titles=' + title + '&format=json&pllimit=500&plnamespace=0&plcontinue=' + plcontinue + '&callback=?';
      }
      $.ajax({url: url, 
          dataType: 'json',
          async: false,
          success: function(data) {
              for (key in data['query']['pages']) {
                  links = data['query']['pages'][key]['links'];
              }
              for (var i = 0; i < links.length; i += 1) {
                  returnArray.push(links[i]['title']);
              }
              if (data.hasOwnProperty('query-continue')) {
                  plcontinue = data['query-continue']['links']['plcontinue'];
              } else {
                  plcontinue = '';
              }
              console.log(returnArray);
              return getLinksFrom(title, returnArray, plcontinue);
          }
      });
  }
  console.log(returnArray);
  return returnArray;
}

この関数を実行してコンソールを見ると、console.log(returnArray); 行は、私が望むものをコンソールに入れます。文字列の配列。しかし、ここで私は混乱します。

その returnArray を、links という変数に格納したいと思います。関数の下にある行は次のとおりです。

var links = getLinksFrom('United States');

しかし、リンクは、以前にログに記録された素晴らしいものと同じになるわけではありません。代わりに、適切な長さではないオブジェクトの配列が含まれています。

ここで何が起こっているのですか?

4

1 に答える 1

2

は非同期関数であるためgetLinksFrom、JS が関数呼び出しを評価すると、linksすぐに結果が変数に書き込まれます。でもその時点でreturnArray空っぽ!

写真を見てください:

ここに画像の説明を入力

へのプッシュはreturnArray、変数に割り当てた後links、そしておそらくこの変数を使用した後に行われることを示しています。

したがって、非同期コードを使用する場合は、単に行うことはできませんa = b()。通常、この場合、人々はコールバックを使用します: b(function(a) { /* do something with a */ })(引数は一種の「成功」関数です)。そのため、コールバックを使用して非同期で動作するようにコードを書き直す必要があります。

しかし、コードにはもう 1 つ問題があります。それは、自己呼び出しを停止しないことです。リクエストが成功するたびに、別のリクエストを送信し、停止することはありません。おそらく、いくつかのリクエストの後、有用なデータを取得できなくなるので、リモートサーバーとユーザーのネットワークに無駄なリクエストを送信する必要はありません。完了したら再帰を行わないでください。その代わりに、callback呼び出して関数の呼び出し元に完了したことを通知できます。

于 2013-02-06T08:25:10.643 に答える