Предотвращение повторения при использовании функций обратного вызова и асинхронных запросов - PullRequest
1 голос
/ 22 сентября 2010

Я пишу некоторый код Javascript / jQuery, который требует от меня большого количества запросов к различным API. Я сталкивался с этой проблемой много раз, и это лишь один из основных примеров.

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

var container = [];

$.getJSON("http://www.url.com/api/?callback=?", 
{ data: "mydata" }, 
function(data) {
    if(!data.length) {
        // No results
    } else {

        // Put the results into an array
        $(data).each(function(k, v){
            container.push(v.some_data);
        });

        // If the query did not return enough results
        if(data.length < limit) {
            var number_missing = limit - data.length;

            // Get some more results and append to the array
            myFunctionToGetSomethingElse(number_missing, function(response){

                // Add these results to the array
                $(response).each(function(k, v){
                    container.push(v.some_data);
                });

                // Do something with this data
                returnFunction(response);
            });

        } else {
            // Do something with the result
            returnFunction(data);
        }
    }
});

Как бы вы порекомендовали мне избегать повторения кода внутри обратных вызовов? Это единственный возможный способ?

Ответы [ 3 ]

2 голосов
/ 22 сентября 2010
// <script src="http://code.onilabs.com/0.9.1/oni-apollo.js"></script>
// <script type="text/sjs">

// install stratified versions of jquery functions; see below
require('jquery-binding').install();

// Note the extra '$' in $getJSON. This is the 'stratified' version of
// getJSON. Instead of taking a callback it blocks until the result is
// available. The browser will stay responsive during that time.

var data = $.$getJSON("http://www.url.com/api/?callback=?", {data: "mydata"});
if (!data.length) {
  // no results
} else {

  $(data).each(function(k, v){
    container.push(v.some_data);
  });

  if (data.length < limit) {
    var number_missing = limit - data.length;
    // assuming your function 'myFunctionToGetSomethingElse' uses
    // something like $.$getJSON inside, again you don't need a
    // callback
    $(myFunctionToGetSomethingElse(number_missing)).each(
      function(k, v){
        container.push(v.some_data);
      });
    }
}

// console.log(container);
// do something with the result. E.g. call returnFunction() or put the
// code from returnFunction here directly

Вы можете получить больше информации о http://onilabs.com/apollo

1 голос
/ 22 сентября 2010

Есть библиотека, доставляющая "стратифицированный javascript". Как ни странно, он превращает асинхронные вызовы в последовательную парадигму. Вернуться на круги своя:)

Взгляните на oni labs .

0 голосов
/ 22 сентября 2010

У меня нет ответа на ваш вопрос - как устранить дублирование, но один из способов сделать это немного чище - это сгладить его с ранним возвратом.

$.getJSON("http://www.url.com/api/?callback=?", 
{ data: "mydata" }, 
function(data) {
    if (!data.length) {
        // No results
        return;
    }  // no "else" needed, because we left the function

    // Put the results into an array
    $(data).each(function(k, v){
        container.push(v.some_data);
    });

    // if the query DID return enough results, return them and exit
    if (data.length >= limit {
        // Do something with the result
        returnFunction(data);
        return;
    } // again, no "else" needed; we don't need to deeply nest the code

    // The query did not return enough results
    var number_missing = limit - data.length;

    // Get some more results and append to the array
    myFunctionToGetSomethingElse(number_missing, function(response){

        // Add these results to the array
        $(response).each(function(k, v){
            container.push(v.some_data);
        });

        // Do something with this data
        returnFunction(response);
        });
    }
});

Я быдумаю, вы могли бы обернуть цикл загрузки массива в его собственную функцию;Я не понимаю, почему это может быть проблемой, но я не знаю javascript достаточно хорошо, чтобы сказать это с абсолютной уверенностью.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...