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

2

Быстрый вопрос о том, как использовать 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 мс позже - то, что я хочу, конечно, наоборот - что через две секунды я получаю «то, что я говорю». а затем «ах»; сразу после.

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

doIt().then( console.log('ah')); логи сразу, потому что это выполняетсяconsole.log а затем передает возврат этогоthen. Armatus
это не синхронно - использованиеsetTimeout делает это асинхронным. Alnitak
@Armatus хорошо, спасибо, это имеет смысл, я знал, что синтаксис второй цепочки doIt () все равно был неправильным. Но как насчет первой цепочки doIt ()? Почему doIt () не возвращает обещание, которое разрешается при возврате sayIt (2000)? заранее спасибо! Petrov
@ Петров, ты никогдаresolve обещание. Alnitak

Ваш Ответ

2   ответа
3

вам нужно вызвать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 
10

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

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() который впоследствии зарегистрирован на нем продолжается сразу.

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

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

Похожие вопросы