comparison 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
comparison
equal deleted inserted replaced
95:0141a165d032 96:daffa72a1cec
349 /// <typeparam name="TNew">Новый тип результата.</typeparam> 349 /// <typeparam name="TNew">Новый тип результата.</typeparam>
350 /// <param name="mapper">Преобразование результата к новому типу.</param> 350 /// <param name="mapper">Преобразование результата к новому типу.</param>
351 /// <param name="error">Обработчик ошибки. Данный обработчик получит 351 /// <param name="error">Обработчик ошибки. Данный обработчик получит
352 /// исключение возникшее при выполнении операции.</param> 352 /// исключение возникшее при выполнении операции.</param>
353 /// <returns>Новое обещание, которое будет выполнено при выполнении исходного обещания.</returns> 353 /// <returns>Новое обещание, которое будет выполнено при выполнении исходного обещания.</returns>
354 /// <param name = "cancel"></param>
354 public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<TNew> error, Action cancel) { 355 public IPromise<TNew> Then<TNew>(ResultMapper<T, TNew> mapper, ErrorHandler<TNew> error, Action cancel) {
355 Safe.ArgumentNotNull(mapper, "mapper"); 356 Safe.ArgumentNotNull(mapper, "mapper");
356 357
357 // создаем прицепленное обещание 358 // создаем прицепленное обещание
358 var medium = new Promise<TNew>(this, true); 359 var medium = new Promise<TNew>(this, true);
411 /// <typeparam name="TNew">Тип результата указанной асинхронной операции.</typeparam> 412 /// <typeparam name="TNew">Тип результата указанной асинхронной операции.</typeparam>
412 /// <param name="chained">Асинхронная операция, которая должна будет начаться после выполнения текущей.</param> 413 /// <param name="chained">Асинхронная операция, которая должна будет начаться после выполнения текущей.</param>
413 /// <param name="error">Обработчик ошибки. Данный обработчик получит 414 /// <param name="error">Обработчик ошибки. Данный обработчик получит
414 /// исключение возникшее при выполнении текуещй операции.</param> 415 /// исключение возникшее при выполнении текуещй операции.</param>
415 /// <returns>Новое обещание, которое будет выполнено по окончанию указанной аснхронной операции.</returns> 416 /// <returns>Новое обещание, которое будет выполнено по окончанию указанной аснхронной операции.</returns>
417 /// <param name = "cancel"></param>
416 public IPromise<TNew> Chain<TNew>(ResultMapper<T, IPromise<TNew>> chained, ErrorHandler<IPromise<TNew>> error, Action cancel) { 418 public IPromise<TNew> Chain<TNew>(ResultMapper<T, IPromise<TNew>> chained, ErrorHandler<IPromise<TNew>> error, Action cancel) {
417 419
418 Safe.ArgumentNotNull(chained, "chained"); 420 Safe.ArgumentNotNull(chained, "chained");
419 421
420 // проблема в том, что на момент связывания еще не начата асинхронная операция, поэтому нужно 422 // проблема в том, что на момент связывания еще не начата асинхронная операция, поэтому нужно
757 759
758 #region IPromiseBase explicit implementation 760 #region IPromiseBase explicit implementation
759 761
760 IPromise IPromise.Then(Action success, ErrorHandler error, Action cancel) { 762 IPromise IPromise.Then(Action success, ErrorHandler error, Action cancel) {
761 return Then( 763 return Then(
762 x => success(), 764 success != null ? new ResultHandler<T>(x => success()) : null,
763 e => { 765 error != null ? new ErrorHandler<T>(e => {
764 error(e); 766 error(e);
765 return default(T); 767 return default(T);
766 }, 768 }) : null,
767 cancel 769 cancel
768 ); 770 );
769 } 771 }
770 772
771 IPromise IPromise.Then(Action success, ErrorHandler error) { 773 IPromise IPromise.Then(Action success, ErrorHandler error) {
772 return Then( 774 return Then(
773 x => success(), 775 success != null ? new ResultHandler<T>(x => success()) : null,
774 e => { 776 error != null ? new ErrorHandler<T>(e => {
775 error(e); 777 error(e);
776 return default(T); 778 return default(T);
777 } 779 }) : null
778 ); 780 );
779 } 781 }
780 782
781 IPromise IPromise.Then(Action success) { 783 IPromise IPromise.Then(Action success) {
784 Safe.ArgumentNotNull(success, "success");
782 return Then(x => success()); 785 return Then(x => success());
783 } 786 }
787
788 IPromise IPromise.Chain(Func<IPromise> chained, ErrorHandler<IPromise> error, Action cancel) {
789 return ChainNoResult(chained, error, cancel);
790 }
791
792 IPromise ChainNoResult(Func<IPromise> chained, ErrorHandler<IPromise> error, Action cancel) {
793 Safe.ArgumentNotNull(chained, "chained");
794
795 var medium = new Promise<object>(this, true);
796
797 ResultHandler<T> resultHandler = delegate(T result) {
798 if (medium.IsCancelled)
799 return;
800
801 var promise = chained();
802
803 promise.Last(
804 medium.Resolve,
805 medium.Reject,
806 () => medium.Reject(new OperationCanceledException()) // внешняя отмена связанной операции рассматривается как ошибка
807 );
808
809 // notify chained operation that it's not needed anymore
810 // порядок вызова Then, Cancelled важен, поскольку от этого
811 // зависит IsExclusive
812 medium.Cancelled(() => {
813 if (promise.IsExclusive)
814 promise.Cancel();
815 });
816 };
817
818 ErrorHandler<T> errorHandler;
819
820 if (error != null)
821 errorHandler = delegate(Exception e) {
822 try {
823 var promise = error(e);
824
825 promise.Last(
826 medium.Resolve,
827 medium.Reject,
828 () => medium.Reject(new OperationCanceledException()) // внешняя отмена связанной операции рассматривается как ошибка
829 );
830
831 // notify chained operation that it's not needed anymore
832 // порядок вызова Then, Cancelled важен, поскольку от этого
833 // зависит IsExclusive
834 medium.Cancelled(() => {
835 if (promise.IsExclusive)
836 promise.Cancel();
837 });
838 } catch (Exception e2) {
839 medium.Reject(e2);
840 }
841 return default(T);
842 };
843 else
844 errorHandler = err => {
845 medium.Reject(err);
846 return default(T);
847 };
848
849
850 Action cancelHandler;
851 if (cancel != null)
852 cancelHandler = () => {
853 if (cancel != null)
854 cancel();
855 medium.Cancel();
856 };
857 else
858 cancelHandler = medium.Cancel;
859
860 AddHandler(
861 resultHandler,
862 errorHandler,
863 cancelHandler,
864 null
865 );
866
867 return medium;
868 }
869 IPromise IPromise.Chain(Func<IPromise> chained, ErrorHandler<IPromise> error) {
870 return ChainNoResult(chained, error, null);
871 }
872 IPromise IPromise.Chain(Func<IPromise> chained) {
873 return ChainNoResult(chained, null, null);
874 }
875
784 876
785 void IPromise.Last(Action success, ErrorHandler error, Action cancel) { 877 void IPromise.Last(Action success, ErrorHandler error, Action cancel) {
786 Last(x => success(), error, cancel); 878 Last(x => success(), error, cancel);
787 } 879 }
788 880