Setting variable to result of function acting very

2019-09-07 02:56发布

问题:

I have a function in javascript that is supposed to return an array of all the articles linked to by a wikipedia page, given the title.

Here it is:

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;
}

When I run this function and watch the console, the console.log(returnArray); lines put what I want in the console. Arrays of strings. But here's where I get confused.

I want to store that returnArray, in a variable called links. Here's that line, which is below the function.

var links = getLinksFrom('United States');

But links doesn't end up equalling that wonderful thing that was logged before. Instead, it contains an array of objects, that isn't the right length.

What's happening here?

回答1:

Since getLinksFrom is asynchronous function, when JS evaluates function call it writes result to the links variable immediately. But at that point of time returnArray is empty!

Take a look at the picture:

It shows that pushing to the returnArray happens after assigning it to the links variable and, most likely, after using this variable.

So if you use asynchronous code, you cant't just do a = b(). Usually in this case people use callbacks: b(function(a) { /* do something with a */ }) (argument is kind of a "success" function). So you should rewrite your code to work asynchronously using callbacks.

But there is one more problem with you code: you never stop self-calls. After every successfull request you send another and never stop. Maybe, after several requests you woun't get any usefull data anymore, so why bother remote server and user's network with useless requests? Just don't do recursion when you're done. Instead of that you can call callback to inform your function caller that you're done.