суббота, 4 февраля 2012 г.

Архитектура "CommonJS Promises/A" и jQuery

Суть патерна состоит в том, что мы получаем обькт обещяния, который имеет набор методов, в которые можно передавать колбеки, а они вяжутся в очереди. Если мы добавили колбек, а событие на которое мы подписываемся через конкретный метод уже произошло, колбек немедленно выполнится, если же не произошло, то колбек попадает в очередь, и он будет выполнен в порядке очереди, как только событие произойдет.


В jQuery этот патерн реализован через обьект Deferred, его метод промис возвращает обьект обещания.
deferred.promise( [target] )
targetObject - это обьект на который нацепятся методы обещания.
 Содержание обьекта, который возвращается из (new jQuery.Deferred()).promise(), тоесть цель для обещаных методов создается с нуля, а не передается атрибутом в функцию):
{
  always: function(){..}, //подписываем сюда колбеки, которые выполнятся в любом варианте, что деферед был отвергнут, что - выполнен.
  done: function(){..}, //подписываем колбеки, которые вызовутся только в случае успешного выполнения
  fail: function(){..}, //переданные сюда колбеки выполняться, когда 
деферед будет отвергнут
  isRejected: function(){..}, //@deprecated с 1.7, лучше пользоваться state()
  isResolved: function(){..}, //@deprecated с 1.7, лучше пользоваться state()
  pipe: function(){..},//принимает два аргумента, с 1.7 три. Первый колбек для фильтрирования успешного результата, второй - реджекта, ну и третий - промежуточных состояний. Возврашает эта функция обещание подписываясь на которые в колбеках мы будем получать отфильтрированные результаты.
  progress: function(){..},//с 1.7. Принимает один аргумент колбек или массив колбеков, которые будут вызываться на изменение промежуточного состояния deffered(by notify или notifyWith), возврашает тоже deffered обьект, в которые мы можем дальше присваивать по цепочке колбеки. Специфика подписи на изменения состояний в том, что если деферед уже отработал, то подписанные после уже мгновенно вызываться не будут.
  promise: function(){..},//непоянтно только зачем обещанию создавать еще одно обещание:-) 
  state: function(){..},//возможны три значения на выходе:"pending", "resolved", "rejected"  - первый возвращается, когда еще ни реджект и резолв на дефереде не был вызван.
  then: function(){..}//сюда можно одновременно передать колбеки для успешного выполнения(1-й аргумент), а 2-м аргументом для неудачного, и с версии 1.7 те, которые будут реагировать на изменение промежуточных состояния
}
Тоеть присваюются только те методы обьета deferred, которые подписывают колбеки и информируют о состоянии, но не те, которые меняют состояния и вызывают обработку, а вот полный список методов обьекта deferred:
{
  always: function(){..},
  done: function(){..},
  fail: function(){..},
  isRejected: function(){..},
  isResolved: function(){..},
  pipe: function(){..},
  progress: function(){..},
  promise: function(){..},
  state: function(){..},
  then: function(){..},

  notify: function(args),//вызывая эту функцию, мы передаем в нее аргументы, которые попадут в колбеки пром.состояний, которые были подписанны через deferred.then или deferred.progress
  notifyWith: function(context[, args]),//аналог предыдущей функции, но еще передается контекст, на который будет ссылаться this в колблеках.
  reject: function(args),//создатель обьекта deffered таким образом сообщает об неудачном завершении операции. Все колбеки, которые были подписанны через deferred/promise.then or deferred/promise.fail будут вызваны, при этом им передадутся аргументы args
  rejectWith: function(),//аналог предыдущей функции, но еще передается контекст, на который будет ссылаться this в колблеках.
  resolve: function(),//создатель обьекта deffered таким образом сообщает об удачном завершении операции. Все колбеки, которые были подписанны через deferred/promise.then or deferred/promise.done будут вызваны, при этом им передадутся аргументы args
  resolveWith:function()//аналог предыдущей функции, но еще передается контекст, на который будет ссылаться this в колблеках.
}

Вот примеры применения обещаний пропущеных через pipe:

var defer = $.Deferred(),
    filtered = defer.pipe( null, function( value ) {
      return value * 3;
    });

defer.reject( 6 );
filtered.fail(function( value ) {
  alert( "Value is ( 3*6 = ) 18: " + value );
});

//EXAMPLE 2

var request = $.ajax( url, { dataType: "json" } ),
    chained = request.pipe(function( data ) {
      return $.ajax( url2, { data: { user: data.userId } } );
    });

chained.done(function( data ) {
  // data retrieved from url2 as provided by the first request
});

Комментариев нет:

Отправить комментарий