синтаксис для Jquery.deferred, обещая синхронную функцию возврата

Быстрый вопрос о том, как использовать Jquery.deferred, чтобы медленная синхронная функция возвращала обещание. На данный момент я сделал следующее:

function sayIt(ms) {
    setTimeout( function() { console.log('what I say'); }, ms);
} 

function doIt() {
    return $.Deferred( function() { sayIt(2000); }).promise();
}


doIt().then( function() { console.log('ah'); });

sayIt (2000) всегда проходит, но цепочечная функция после «затем» никогда не стреляет

Если я сделаю это:

doIt().then( console.log('ah'));

«ах» подходит сразу, а затем «то, что я говорю»; 2000 мс позже - то, что я хочу, конечно, наоборот - что через две секунды я получаю «то, что я говорю». а затем «ах»; сразу после.

Любые предложения приветствуются!

 Petrov19 мая 2012 г., 13:04
@Armatus хорошо, спасибо, это имеет смысл, я знал, что синтаксис второй цепочки doIt () все равно был неправильным. Но как насчет первой цепочки doIt ()? Почему doIt () не возвращает обещание, которое разрешается при возврате sayIt (2000)? заранее спасибо!
 Alnitak19 мая 2012 г., 13:05
это не синхронно - использованиеsetTimeout делает это асинхронным.
 Armatus19 мая 2012 г., 12:59
doIt().then( console.log('ah')); логи сразу, потому что это выполняетсяconsole.log а затем передает возврат этогоthen.
 Alnitak19 мая 2012 г., 13:09
@ Петров, ты никогдаresolve обещание.

Ответы на вопрос(2)

вам нужно вызватьresolve() наDeferred объект из функции истечения времени ожидания:

function sayIt(ms) {
  var d = $.Deferred();
  setTimeout(function() {
      console.log('what I say');
      d.resolve()
    }, ms);
  return d;
}

Таким образом, вы ограничиваете разрешениеDeferred возражать против истечения времени ожидания.

Чтобы достичь того, что я считаю твоим намерением:

function doIt() {
  return sayIt(2000).promise()
}

.promise() Звонить необязательно. Это только ограничивает доступный интерфейс для вызывающих: возвращаяPromise вместо оригиналаDeferred объект, вызывающий может реагировать только на события, но не запускать их. Ссылка:http://api.jquery.com/deferred.promise/.

В конце концов, ваш оригинальный звонок:

doIt().then( function() { console.log('ah'); });

Будет выводить:

// 2 seconds delay
what I say
ah 
Решение Вопроса

но все же использовать обещание, выполните:

function slowPromise() {

    var def = $.Deferred();

    // do something slow and synchronous
    ...

    // resolve the deferred with the result of the slow process
    def.resolve(res);

    // and return the deferred
    return def.promise();
}

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

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

 19 мая 2012 г., 13:44
@ Петров смjsfiddle.net/alnitak/HvzV3
 19 мая 2012 г., 13:42
@Petrov & quot; медленный & quot; не совпадает с "синхронным". Ты долженresolve обещаниеat the end of the async function.
 Petrov19 мая 2012 г., 13:18
Вот jsfiddle вашего решения:jsfiddle.net/petrov/nzDae но кажется, что он делает то же самое - «конец»; наступает раньше, чем "середина" ...
 Petrov19 мая 2012 г., 14:53
@ Alnitak спасибо за ваши ответы. Я прочитал немного больше, и то, что я действительно хотел сделать, не возможно, но ваш пример был превосходным и заставил меня увидеть это.
 Petrov19 мая 2012 г., 13:36
я вижу в jsfiddle выше, что def.resolve (результат) запускается сразу с еще неопределенным «результатом», потому что медленная функция еще не вернулась. проблема состоит в том, что sayIt не запускает событие, когда оно завершено

Ваш ответ на вопрос