# HG changeset patch # User cin # Date 2014-10-30 07:06:16 # Node ID daffa72a1cec3507401e2294a6912902c20e351d # Parent 0141a165d0329eb4588335c2da64e3802bc0aa65 Added the chaining method to the non-generic IPromise diff --git a/Implab/IPromise.cs b/Implab/IPromise.cs --- a/Implab/IPromise.cs +++ b/Implab/IPromise.cs @@ -31,6 +31,10 @@ namespace Implab { IPromise Then(Action success, ErrorHandler error); IPromise Then(Action success); + IPromise Chain(Func chained, ErrorHandler error, Action cancel); + IPromise Chain(Func chained, ErrorHandler error); + IPromise Chain(Func chained); + /// /// Добавляет последнй обработчик в цепочку обещаний, не создает промежуточных обещаний. /// diff --git a/Implab/Promise.cs b/Implab/Promise.cs --- a/Implab/Promise.cs +++ b/Implab/Promise.cs @@ -351,6 +351,7 @@ namespace Implab { /// Обработчик ошибки. Данный обработчик получит /// исключение возникшее при выполнении операции. /// Новое обещание, которое будет выполнено при выполнении исходного обещания. + /// public IPromise Then(ResultMapper mapper, ErrorHandler error, Action cancel) { Safe.ArgumentNotNull(mapper, "mapper"); @@ -413,6 +414,7 @@ namespace Implab { /// Обработчик ошибки. Данный обработчик получит /// исключение возникшее при выполнении текуещй операции. /// Новое обещание, которое будет выполнено по окончанию указанной аснхронной операции. + /// public IPromise Chain(ResultMapper> chained, ErrorHandler> error, Action cancel) { Safe.ArgumentNotNull(chained, "chained"); @@ -759,29 +761,119 @@ namespace Implab { IPromise IPromise.Then(Action success, ErrorHandler error, Action cancel) { return Then( - x => success(), - e => { + success != null ? new ResultHandler(x => success()) : null, + error != null ? new ErrorHandler(e => { error(e); return default(T); - }, + }) : null, cancel ); } IPromise IPromise.Then(Action success, ErrorHandler error) { return Then( - x => success(), - e => { + success != null ? new ResultHandler(x => success()) : null, + error != null ? new ErrorHandler(e => { error(e); return default(T); - } + }) : null ); } IPromise IPromise.Then(Action success) { + Safe.ArgumentNotNull(success, "success"); return Then(x => success()); } + IPromise IPromise.Chain(Func chained, ErrorHandler error, Action cancel) { + return ChainNoResult(chained, error, cancel); + } + + IPromise ChainNoResult(Func chained, ErrorHandler error, Action cancel) { + Safe.ArgumentNotNull(chained, "chained"); + + var medium = new Promise(this, true); + + ResultHandler resultHandler = delegate(T result) { + if (medium.IsCancelled) + return; + + var promise = chained(); + + promise.Last( + medium.Resolve, + medium.Reject, + () => medium.Reject(new OperationCanceledException()) // внешняя отмена связанной операции рассматривается как ошибка + ); + + // notify chained operation that it's not needed anymore + // порядок вызова Then, Cancelled важен, поскольку от этого + // зависит IsExclusive + medium.Cancelled(() => { + if (promise.IsExclusive) + promise.Cancel(); + }); + }; + + ErrorHandler errorHandler; + + if (error != null) + errorHandler = delegate(Exception e) { + try { + var promise = error(e); + + promise.Last( + medium.Resolve, + medium.Reject, + () => medium.Reject(new OperationCanceledException()) // внешняя отмена связанной операции рассматривается как ошибка + ); + + // notify chained operation that it's not needed anymore + // порядок вызова Then, Cancelled важен, поскольку от этого + // зависит IsExclusive + medium.Cancelled(() => { + if (promise.IsExclusive) + promise.Cancel(); + }); + } catch (Exception e2) { + medium.Reject(e2); + } + return default(T); + }; + else + errorHandler = err => { + medium.Reject(err); + return default(T); + }; + + + Action cancelHandler; + if (cancel != null) + cancelHandler = () => { + if (cancel != null) + cancel(); + medium.Cancel(); + }; + else + cancelHandler = medium.Cancel; + + AddHandler( + resultHandler, + errorHandler, + cancelHandler, + null + ); + + return medium; + } + IPromise IPromise.Chain(Func chained, ErrorHandler error) { + return ChainNoResult(chained, error, null); + } + IPromise IPromise.Chain(Func chained) { + return ChainNoResult(chained, null, null); + } + + void IPromise.Last(Action success, ErrorHandler error, Action cancel) { Last(x => success(), error, cancel); } diff --git a/Implab/Safe.cs b/Implab/Safe.cs --- a/Implab/Safe.cs +++ b/Implab/Safe.cs @@ -58,7 +58,7 @@ namespace Implab } [DebuggerStepThrough] - public static IPromise InvokePromise(Action action) { + public static IPromise InvokePromise(Action action) { ArgumentNotNull(action, "action"); var p = new Promise();