Mercurial > pub > ImplabNet
diff Implab/Promise.cs @ 96:daffa72a1cec v2
Added the chaining method to the non-generic IPromise
author | cin |
---|---|
date | Thu, 30 Oct 2014 10:06:16 +0300 |
parents | 4f20870d0816 |
children | 8ddf1648eca4 |
line wrap: on
line diff
--- a/Implab/Promise.cs Wed Oct 29 18:54:46 2014 +0300 +++ b/Implab/Promise.cs Thu Oct 30 10:06:16 2014 +0300 @@ -351,6 +351,7 @@ /// <param name="error">Обработчик ошибки. Данный обработчик получит /// исключение возникшее при выполнении операции.</param> /// <returns>Новое обещание, которое будет выполнено при выполнении исходного обещания.</returns> + /// <param name = "cancel"></param> public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<TNew> error, Action cancel) { Safe.ArgumentNotNull(mapper, "mapper"); @@ -413,6 +414,7 @@ /// <param name="error">Обработчик ошибки. Данный обработчик получит /// исключение возникшее при выполнении текуещй операции.</param> /// <returns>Новое обещание, которое будет выполнено по окончанию указанной аснхронной операции.</returns> + /// <param name = "cancel"></param> public IPromise<TNew> Chain<TNew>(ResultMapper<T, IPromise<TNew>> chained, ErrorHandler<IPromise<TNew>> error, Action cancel) { Safe.ArgumentNotNull(chained, "chained"); @@ -759,29 +761,119 @@ IPromise IPromise.Then(Action success, ErrorHandler error, Action cancel) { return Then( - x => success(), - e => { + success != null ? new ResultHandler<T>(x => success()) : null, + error != null ? new ErrorHandler<T>(e => { error(e); return default(T); - }, + }) : null, cancel ); } IPromise IPromise.Then(Action success, ErrorHandler error) { return Then( - x => success(), - e => { + success != null ? new ResultHandler<T>(x => success()) : null, + error != null ? new ErrorHandler<T>(e => { error(e); return default(T); - } + }) : null ); } IPromise IPromise.Then(Action success) { + Safe.ArgumentNotNull(success, "success"); return Then(x => success()); } + IPromise IPromise.Chain(Func<IPromise> chained, ErrorHandler<IPromise> error, Action cancel) { + return ChainNoResult(chained, error, cancel); + } + + IPromise ChainNoResult(Func<IPromise> chained, ErrorHandler<IPromise> error, Action cancel) { + Safe.ArgumentNotNull(chained, "chained"); + + var medium = new Promise<object>(this, true); + + ResultHandler<T> 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<T> 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<IPromise> chained, ErrorHandler<IPromise> error) { + return ChainNoResult(chained, error, null); + } + IPromise IPromise.Chain(Func<IPromise> chained) { + return ChainNoResult(chained, null, null); + } + + void IPromise.Last(Action success, ErrorHandler error, Action cancel) { Last(x => success(), error, cancel); }