Лучший способ определить, когда переменная! = Undefined при отправке асинхронного запроса - PullRequest
1 голос
/ 01 июня 2011

Учитывая следующее:

var doThings = (function ($, window, document) { 
  var someScopedVariable = undefined,
      methods,
      _status;

  methods = { 
    init: function () { 
      _status.getStatus.call(this);

      // Do something with the 'someScopedVariable'
    }
  };

  // Local method
  _status = { 
    getStatus: function () { 
      // Runs a webservice call to populate the 'someScopedVariable'

      if (someScopedVariable === undefined) { 
        _status.setStatus.call(this);
      }

      return someScopedVariable;

    },
    setStatus: function () { 
      $.ajax({
           url: "someWebservice",
           success: function(results){
              someScopedVariable = results;
           }
         });
    }
  };

  return methods;

} (jQuery, window, document));

Проблема ясна, это асинхронная ситуация, в которой я хотел бы подождать, пока someScopedVariable не станет неопределенной, а затем продолжить.

IЯ думал об использовании отложенного вызова .when () -> .done () в jQuery, но я не могу заставить его работать.Я также подумал о создании цикла, который бы просто проверял, определен ли он, но это не выглядит элегантно.

Возможный вариант 1:

$.when(_status.getStatus.call(this)).done(function () {
        return someScopedVariable; 
});

Возможный вариант 2 (Ужасный параметр):

_status.getStatus.call(this)

var i = 0;
do {
  i++;
} while (formStatusObject !== undefined);

return formStatusObject;

ОБНОВЛЕНИЕ: Полагаю, я вычеркнул слишком много логики, чтобы объяснить ее, поэтому добавил в некоторые.Целью этого было создание средства доступа к этим данным.

Ответы [ 3 ]

4 голосов
/ 01 июня 2011

Я бы предложил дождаться события завершения / успеха вызова ajax.

  methods = { 
    init: function () { 
      _status.getStatus.call(this);
    },
    continueInit: function( data ) {
      // populate 'someScopedVariable' from data and continue init
    }
  };

  _status = { 
    getStatus: function () { 
      $.post('webservice.url', continueInit );
    }
  };
1 голос
/ 01 июня 2011

Вы не можете заблокировать использование бесконечного цикла для ожидания завершения асинхронного запроса, поскольку ваш JavaScript, скорее всего, выполняется в одном потоке. Движок JavaScript будет ждать завершения вашего скрипта, прежде чем попытаться вызвать асинхронный обратный вызов, который изменит переменную, которую вы смотрите в цикле. Следовательно, возникает тупик.

Единственный способ - использовать функции обратного вызова, как во втором варианте.

0 голосов
/ 01 июня 2011

Я согласен с другим ответом об использовании обратного вызова, если это возможно.Если по какой-то причине вам нужно заблокировать и дождаться ответа, не используйте циклический подход, это самый худший из возможных способов сделать это.Наиболее простым будет использование set async:false в вашем вызове ajax.

См. http://api.jquery.com/jQuery.ajax/

async - Boolean По умолчанию: true По умолчанию все запросы отправляются асинхронно (т.е.по умолчанию установлено значение true).Если вам нужны синхронные запросы, установите для этого параметра значение false.Междоменные запросы и dataType: запросы «jsonp» не поддерживают синхронную работу.Обратите внимание, что синхронные запросы могут временно блокировать браузер, отключая любые действия, когда запрос активен.

...