Инкремент только после завершения предыдущего взаимодействия (обратный вызов)

0

У меня проблема с функциями обратного вызова в javascript. То, что я хочу сделать, это: loop on a for и вызов функции, передающей i как параметр. Имея это в виду, мне нужно перейти к следующему взаимодействию только после того, как предыдущий закончен. Я не знаю, если это проблема, но внутри функции я представляемый i в качестве параметра, у меня есть еще одна функции обратного вызова. Вот мой код:

for(i=0; i<10; i++) {
    aux(i, function(success) {
        /* 
         *  this should be made interaction by interaction
         *  but what happens is: while I'm still running my first interaction  
         *  (i=0), the code loops for i=1, i=2, etc. before the response of 
         *  the previous interaction
         */
        if(!success)
            doSomething();
        else
            doSomethingElse();
    });
}

function aux(i, success) {
    ... //here I make my logic with "i" sent as parameter
    getReturnFromAjax(function(response) {
        if(response)
            return success(true);
        else
            return success(false);
    });
});

function getReturnFromAjax(callback) {
    ...
    $.ajax({ 
        url: myUrl,
        type: "POST",
        success: function (response) {
        return callback(response);
    }
});
}
Теги:
callback

3 ответа

1
Лучший ответ

jQuery Deferred могут быть немного сложными, чтобы получить право. То, что вам нужно сделать, это укладывать свои обещания в цепочку. Например:

var
  // create a deferred object
  dfd = $.Deferred(),

  // get the promise
  promise = dfd.promise(),

  // the loop variable
  i
;

for(i = 0; i < 10; i += 1) {
  // use 'then' and use the new promise for next itteration
  promise = promise.then(
    // prepare the function to be called, but don't execute it!
    // (see docs for .bind)
    aux.bind(null, i, function(success) {
      success ? doSomethingElse() : doSomething();
    })
  );
}

// resolve the deferred object
dfd.resolve();

для того, чтобы это работало, aux также должен вернуть обещание, но $.ajax уже делает это, поэтому просто передайте его, и все должно работать:

в aux :

function aux(i, callback) {
  console.log('executing for 'aux' with', i);

  // return the ajax-promise
  return getReturnFromAjax(function(response) {
    callback(Boolean(response));
  });
}

в getReturnFromAjax :

function getReturnFromAjax(callback) {
  // return the ajax-promise
  return $.ajax({
    url: '%your-url%',
    type: '%method%',
    success: function (response) {
      callback(response);
    }
  });
}

demo: http://jsbin.com/pilebofi/2/

1

Я бы предположил, что вы заглянули в jQuery Deferred Objects и jQuery.Deferred() -method вместо того, чтобы создавать собственные функции очереди обратного вызова (так как вы уже используете jQuery).

Описание: Функция-конструктор, которая возвращает цельный объект утилиты с методами регистрации нескольких обратных вызовов в очереди обратного вызова, вызывает очереди обратного вызова и ретранслирует состояние успеха или отказа любой синхронной или асинхронной функции.

0

У меня нет опыта работы с jQuery, но ваш обратный вызов выглядит немного подозрительным для меня.

В простой JS я предлагаю попробовать что-то среди строк этого:

function yourMainFunction
{   

    function callbackHandler(result) 
    {
        // Code that depends on on the result of the callback
    }

    getAjaxResults(callbackHandler);

}



function getAjaxResults(callbackHandler)
{   

// Create xmlHttpRequest Handler, etc.
// Make your AJAX request

xmlHttp.onreadystatechange = function() 
{
    if (xmlHttp.readyState == 4 && xmlHttp.status==200)
    {
        // Do stuff you want to do if the request was successful
        // Define a variable with the value(s) you want to return to the main function

        callbackHandler(yourReturnVariable);
    }
}
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню