Deferred для Javascript (Prototype)

    Prototype and Twisted
    Продолжая тему Deferred для JavaScript предлагаю еще одно переписывание Deferred, теперь в терминах Prototype. Подробнее о самом Deferred можно почитать в двух моих прошлых заметках: Асинхронное программирование: концепция Deferred и Deferred: все подробности. Если кратко, самое распространенное и полезное применение Deferred в JavaScript — это работа с AJAX или другими RPC-over-HTTP вызовами, когда необходимо совершить цепочку логически связанных вызовов, корректно обрабатывать возникающие ошибки и т.п. С моей точки зрения, Deferred крайне необходим в таких ситуациях.

    Перейдем к примерам: обращение к некоторому JSON-RPC API на основе Prototype’овского Ajax.Request можеть быть обернуто в Deferred следующим образом:

    var Api = Class.create({
        initialize: function(url)
        {
            this.url = url;
        },
    
        call: function(method, params)
        {
            var requestBody = $H({ 'method' : method, 'params' : params }).toJSON();
            var d = new Deferred();
    
            var onSuccess = function(transport)
            {
                result = transport.responseText.evalJSON();
                if ('faultCode' in result && 'faultString' in result)
                {
                    var err = new Error(result.faultString);
                    err.faultCode = result.faultCode;
                    err.faultString = result.faultString;
                    d.errback(err);
                }
                else
                {
                    result = result[0];
                    console.log("Got result: ", result);
                    d.callback(result);
                }
            };
    
            var onFailure = function(transport)
            {
                d.errback(new Error("API transport error: " + transport.status))
            };
    
            var onException = function(error)
            {
                d.errback(error);
            }
    
            new Ajax.Request(this.url, {
                    method: 'post',
                    postBody: requestBody,
                    requestHeaders: { 'Content-Type' : 'application/json' },
                    onSuccess: onSuccess,
                    onFailure: onFailure,
                    onException: onException,
                });
    
            return d;
        },
    });
    

    Здесь любое обращение к Api.call будет возвращать новый Deferred, который будет содержать результат удаленного вызова либо исключение (транспортное или от сервера, к которому мы обращаемся). Пусть есть RPC-вызовы sum и mult, которые, соответственно, складывают и перемножают свои аргументы. Тогда вычисление выражения (2+3)*7 с использованием нашего класса Api будет выглядеть так:

      var api = new Api;
      api.call('sum', [2, 3])
         .addCallback(
                   function (sum_of_2_and_3) 
                   { 
                         return api.call('mult', [sum_of_2_and_3, 7]); 
                   })
         .addCallback(
                   function(result)
                   { 
                         alert('(2+3)*7 = ' + result); 
                   })
         .addErrback(
                  function (error) 
                  { 
                         alert('Mmm… something wrong happened: ' + error); 
                  });
    

    Ну и самое главное:
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 6

      –3
      Вы еще не перешли на jquery? Тогда мы идем к вам!
        0
        Все для своих нужд и своих пользователей.
        0
        Андрюха, рад тебя видеть :)
          0
          Взаимно! :)
          +1
          /* люди, эта хренотень вычислят (2+3)*7 */
            var api = new Api;
            api.call('sum', [2, 3])
               .addCallback(
                         function (sum_of_2_and_3) 
                         { 
                               return api.call('mult', [sum_of_2_and_3, 7]);
                         })
               .addCallback(
                         function(result)
                         { 
                               alert('(2+3)*7 = ' + result);
                         })
               .addErrback(
                        function (error) 
                        { 
                               alert('Mmm… something wrong happened: ' + error);
                        });

          сколько нужно программистов для того, чтобы ввернуть лампочку?… ㋡
            0
            Ой как много… Но без Deferred нужно еще больше программистов!

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое