Продолжая тему 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);
});
Ну и самое главное:
- исходный код Deferred.js;
- лицензия MIT, как и у самого первого варианта Deferred для JavaScript.
Comments
Comments powered by Disqus