/// <summary> /// Add a resolved callback, a rejected callback and a progress callback. /// The resolved callback chains a non-value promise. /// </summary> public IPromise Then(Func <PromisedT, IPromise> onResolved, Action <Exception> onRejected, Action <float> onProgress) { if (CurState == PromiseState.Resolved) { try { return(onResolved(resolveValue)); } catch (Exception ex) { return(Promise.Rejected(ex)); } } var resultPromise = new Promise(); resultPromise.WithName(Name); Action <PromisedT> resolveHandler = v => { if (onResolved != null) { onResolved(v) .Progress(progress => resultPromise.ReportProgress(progress)) .Then( () => resultPromise.Resolve(), ex => resultPromise.Reject(ex) ); } else { resultPromise.Resolve(); } }; Action <Exception> rejectHandler; if (onRejected != null) { rejectHandler = ex => { onRejected(ex); resultPromise.Reject(ex); }; } else { rejectHandler = resultPromise.Reject; } ActionHandlers(resultPromise, resolveHandler, rejectHandler); if (onProgress != null) { ProgressHandlers(this, onProgress); } return(resultPromise); }
/// <summary> /// Chain a number of operations using promises. /// Returns the value of the first promise that resolves, or otherwise the exception thrown by the last operation. /// </summary> public static IPromise <T> First <T>(IEnumerable <Func <IPromise <T> > > fns) { var promise = new Promise <T>(); int count = 0; fns.Aggregate( Promise <T> .Rejected(null), (prevPromise, fn) => { int itemSequence = count; ++count; var newPromise = new Promise <T>(); prevPromise .Progress(v => { var sliceLength = 1f / count; promise.ReportProgress(sliceLength * (v + itemSequence)); }) .Then((Action <T>)newPromise.Resolve) .Catch(ex => { var sliceLength = 1f / count; promise.ReportProgress(sliceLength * itemSequence); fn() .Then(value => newPromise.Resolve(value)) .Catch(newPromise.Reject) .Done() ; }) ; return(newPromise); }) .Then(value => promise.Resolve(value)) .Catch(ex => { promise.ReportProgress(1f); promise.Reject(ex); }); return(promise); }
/// <summary> /// Add a resolved callback and a rejected callback. /// The resolved callback chains a value promise (optionally converting to a different value type). /// </summary> public IPromise <ConvertedT> Then <ConvertedT>( Func <PromisedT, IPromise <ConvertedT> > onResolved, Func <Exception, IPromise <ConvertedT> > onRejected ) { if (CurState == PromiseState.Resolved) { try { return(onResolved(resolveValue)); } catch (Exception ex) { return(Promise <ConvertedT> .Rejected(ex)); } } else if (CurState == PromiseState.Rejected) { try { if (onRejected == null) { return(Promise <ConvertedT> .Rejected(rejectionException)); } else { IPromise <ConvertedT> chainedValue = onRejected(rejectionException); return(chainedValue); } } catch (Exception ex) { return(Promise <ConvertedT> .Rejected(ex)); } } else { return(ThenPending(onResolved, onRejected)); } }
/// <summary> /// Add a resolved callback and a rejected callback. /// </summary> public IPromise Then(Action <PromisedT> onResolved, Action <Exception> onRejected) { if (CurState == PromiseState.Resolved) { try { onResolved(resolveValue); return(Promise.Resolved()); } catch (Exception ex) { return(Promise.Rejected(ex)); } } else if (CurState == PromiseState.Rejected) { try { if (onRejected != null) { onRejected(rejectionException); return(Promise.RejectedStatic(rejectionException)); } else { return(Promise.RejectedStatic(rejectionException)); } } catch (Exception ex) { return(Promise.RejectedStatic(ex)); } } else { return(ThenPending(onResolved, onRejected)); } }
/// <summary> /// Add a resolved callback, a rejected callback and a progress callback. /// The resolved callback chains a value promise (optionally converting to a different value type). /// </summary> public IPromise <ConvertedT> Then <ConvertedT>( Func <PromisedT, IPromise <ConvertedT> > onResolved, Func <Exception, IPromise <ConvertedT> > onRejected, Action <float> onProgress ) { if (CurState == PromiseState.Resolved) { try { return(onResolved(resolveValue)); } catch (Exception ex) { return(Promise <ConvertedT> .Rejected(ex)); } } // This version of the function must supply an onResolved. // Otherwise there is now way to get the converted value to pass to the resulting promise. // Argument.NotNull(() => onResolved); var resultPromise = new Promise <ConvertedT>(); resultPromise.WithName(Name); Action <PromisedT> resolveHandler = v => { onResolved(v) .Progress(progress => resultPromise.ReportProgress(progress)) .Then( // Should not be necessary to specify the arg type on the next line, but Unity (mono) has an internal compiler error otherwise. chainedValue => resultPromise.Resolve(chainedValue), ex => resultPromise.Reject(ex) ); }; Action <Exception> rejectHandler = ex => { if (onRejected == null) { resultPromise.Reject(ex); return; } try { onRejected(ex) .Then( chainedValue => resultPromise.Resolve(chainedValue), callbackEx => resultPromise.Reject(callbackEx) ); } catch (Exception callbackEx) { resultPromise.Reject(callbackEx); } }; ActionHandlers(resultPromise, resolveHandler, rejectHandler); if (onProgress != null) { ProgressHandlers(this, onProgress); } return(resultPromise); }