<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Блог Андрея Смирнова (javasc)</title><link>http://www.smira.ru/</link><description></description><language>ru</language><lastBuildDate>Sun, 11 Jan 2015 19:24:25 GMT</lastBuildDate><generator>http://getnikola.com/</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Deferred для JavaScript (Prototype)</title><link>http://www.smira.ru/posts/20090529deferred-in-javascript-for-prototype.html</link><dc:creator>Andrey</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;img src="http://www.smira.ru/wp-content/uploads/2009/05/prototype_twisted.png" alt="Prototype and Twisted" title="Prototype and Twisted" width="200" height="200" class="alignleft size-full wp-image-410"&gt;
&lt;p&gt;&lt;a href="http://www.smira.ru/2008/11/01/open-source-deferred-qooxdoo/"&gt;Продолжая&lt;/a&gt; тему &lt;a href="http://twistedmatrix.com/projects/core/documentation/howto/async.html"&gt;Deferred&lt;/a&gt; для JavaScript предлагаю еще одно переписывание Deferred, теперь в терминах &lt;a href="http://www.prototypejs.org/"&gt;Prototype&lt;/a&gt;. Подробнее о самом Deferred можно почитать в двух моих прошлых заметках: &lt;a href="http://www.smira.ru/2009/02/10/deferred-async-programming/"&gt;Асинхронное программирование: концепция Deferred&lt;/a&gt; и &lt;a href="http://www.smira.ru/2009/02/24/more-about-deferred/"&gt;Deferred: все подробности&lt;/a&gt;. Если кратко, самое распространенное и полезное применение Deferred в JavaScript - это работа с AJAX или другими RPC-over-HTTP вызовами, когда необходимо совершить цепочку логически связанных вызовов, корректно обрабатывать возникающие ошибки и т.п. С моей точки зрения, Deferred крайне необходим в таких ситуациях.&lt;/p&gt;
&lt;p&gt;Перейдем к примерам: обращение к некоторому JSON-RPC API на основе Prototype'овского &lt;a href="http://www.prototypejs.org/api/ajax/request"&gt;Ajax.Request&lt;/a&gt; можеть быть обернуто в Deferred следующим образом:&lt;/p&gt;
&lt;!--more--&gt;

&lt;pre lang="javascript"&gt;

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 &amp;amp;&amp;amp; '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;
    },
});

&lt;/pre&gt;

&lt;p&gt;Здесь любое обращение к &lt;code&gt;Api.call&lt;/code&gt; будет возвращать новый Deferred, который будет содержать результат удаленного вызова либо исключение (транспортное или от сервера, к которому мы обращаемся). Пусть есть RPC-вызовы &lt;code&gt;sum&lt;/code&gt; и &lt;code&gt;mult&lt;/code&gt;, которые, соответственно, складывают и перемножают свои аргументы. Тогда вычисление выражения &lt;code&gt;(2+3)*7&lt;/code&gt; с использованием нашего класса &lt;code&gt;Api&lt;/code&gt; будет выглядеть так:&lt;/p&gt;
&lt;pre lang="javascript"&gt;
  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); 
              });
&lt;/pre&gt;

&lt;p&gt;Ну и самое главное: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;исходный код &lt;a href="http://www.smira.ru/wp-content/uploads/2009/05/deferred.js"&gt;Deferred.js&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;лицензия MIT, как и у самого &lt;a href="http://mochikit.com/doc/html/MochiKit/Async.html"&gt;первого варианта Deferred для JavaScript&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><category>Twisted</category><category>deferred</category><category>javasc</category><category>prototype</category><category>разработка</category><guid>http://www.smira.ru/posts/20090529deferred-in-javascript-for-prototype.html</guid><pubDate>Fri, 29 May 2009 14:35:06 GMT</pubDate></item></channel></rss>