2012-03-17 2 views
0

Я использую API GitHub для получения данных об одном из моего РЕПО, и я бег в проблемы с функциями обратного вызова и рекурсивные функции перекрытием (как в рекурсивных функциях с обратными вызовами прикрепленных к ним)Как работают «рекурсивные обратные вызовы AJAX» в JavaScript?

Here is the script on jsfiddle как показано ниже:

(function() { 
    'use strict'; 

    function makeAJAXCall(hash, cb) { 
     $.ajaxSetup({ 
      accept: 'application/vnd.github.raw', 
      dataType: 'jsonp' 
     }); 

     $.ajax({ 
      url: hash, 
      success: function (json) { 
       //console.info(json); 
       // Time for callback to be executed 
       if (cb) { 
        cb(json); 
       } 
      }, 
      error: function (error) { 
       console.error(error); 
       // an error happened, check it out. 
       throw error; 
      } 
     }); 
    } 

    function parseBlob(hash) { 
     return makeAJAXCall(hash, function (returnedJSON) { // no loop as only one entry 
      console.log(returnedJSON.data); 
      return returnedJSON.data.content; 
     }); 
    } 

    function walkTree(hash) { 
     var tree = 'https://api.github.com/repos/myusername/SVG-Shapes/git/trees/' + hash; 
     return makeAJAXCall(tree, function (objectedJSON) { 
      var objectList = [], i, entry; 
      for (i = 0; i < objectedJSON.data.tree.length; i += 1) { 
       entry = objectedJSON.data.tree[i]; 
       //console.debug(entry); 
       if (entry.type === 'blob') { 
        if (entry.path.slice(-4) === '.svg') {  // we only want the svg images not the ignore file and README etc 
         //console.info(entry.path) 
         objectList.push(parseBlob(entry.url)); 
        } 
       } else if (entry.type === 'tree') { 
        objectList.push(walkTree(entry.sha)); 
       } 
      } 
      if (cb) { 
       console.log(objectList); 
       cb(objectList); 
      } 
      return objectList; 
     }); 
    } 

    $(document).ready(function() { 
     var returnedObjects = walkTree('master', function (objects) {  // master to start at the top and work our way down 
      console.info(objects); 
     }); 
    }); 
}()); 

Возврат JSON - это либо блог (файл), либо дерево (каталог). Если это дерево, функция walkTree вызывается снова. Я не понимаю, как будет вести себя обратный вызов, а также как получить данные, которые он должен вернуть (-а) из функции, и в последний блок в самом низу.

Может кто-то уточнить, как я должен это делать?

ответ

4

Ajax звонки обычно асинхронны. Это означает, что когда вы делаете вызов ajax, он просто инициирует вызов ajax, и он заканчивается через некоторое время. Между тем, остальная часть вашего кода после начала вызова ajax продолжает работать до завершения.

Затем, спустя некоторое время после завершения вызова ajax, вызывается функция успеха и, в вашем случае, функция обратного вызова вызывается функцией успеха. Важно понимать, что функция успеха называется намного позже после того, как функция makeAJAXCall() уже завершена.

Таким образом, вы не можете вернуть данные ajax из функции makeAJAXCall(), так как пока неизвестно, когда эта функция вернется.

В самом деле, только два места, которые вы можете использовать результаты вызова Ajax являются:

  1. В обработчике успеха непосредственно
  2. В некоторой функции, которая вызывает обработчик успеха в вашем случае его функция обратного вызова.

Таким образом, он не делает ничего хорошего для return returnedJSON.data.content; из функции обратного вызова. Это просто возвращается в некоторую внутреннюю часть инфраструктуры ajax и ничего не делает. Это возвращаемое значение будет просто сброшено на пол и потеряно.

Вместо этого вам нужно поставить любой код, который хочет использовать returnedJSON.data.content прямо в этой функции обратного вызова (или передать его другой функции с вызовом функции).

Ajax является асинхронным. Это означает, что вы не можете выполнять нормальное последовательное программирование при использовании ajax. Вместо этого вам нужно программировать на основе событий, где событие в этом случае является обратным вызовом, который вызван успешным завершением вызова ajax. Вся работа, использующая эти результаты ajax, должна начинаться с этого обработчика успеха или вызванного из него обратного вызова.

Смежные вопросы