comparison Implab/PromiseExtensions.cs @ 207:558f34b2fb50 v2

added Safe.DispatchEvent() a legacy equivalent for '?.Invoke()' added Safe.Dispose(IEnumerable) added PromiseExtensions.CancellationPoint to add a cancellation point to the chain of promises added IPromise<T> PromiseExtensions.Then<T>(this IPromise<T> that, Action<T> success) overloads added PromiseExtensions.Error() overloads to handle a error or(and) a cancellation
author cin
date Wed, 09 Nov 2016 12:03:22 +0300
parents 8200ab154c8a
children 7d07503621fe
comparison
equal deleted inserted replaced
206:86b61d53b7db 207:558f34b2fb50
45 /// <param name="that">That.</param> 45 /// <param name="that">That.</param>
46 /// <param name="head">Head.</param> 46 /// <param name="head">Head.</param>
47 /// <param name="cleanup">Cleanup.</param> 47 /// <param name="cleanup">Cleanup.</param>
48 /// <typeparam name="TPromise">The 1st type parameter.</typeparam> 48 /// <typeparam name="TPromise">The 1st type parameter.</typeparam>
49 /// <typeparam name="T">The 2nd type parameter.</typeparam> 49 /// <typeparam name="T">The 2nd type parameter.</typeparam>
50 public static TPromise EnsureDispatched<TPromise,T>(this TPromise that, IPromise<T> head, Action<T> cleanup) where TPromise : IPromise{ 50 public static TPromise EnsureDispatched<TPromise, T>(this TPromise that, IPromise<T> head, Action<T> cleanup) where TPromise : IPromise {
51 Safe.ArgumentNotNull(that, "that"); 51 Safe.ArgumentNotNull(that, "that");
52 Safe.ArgumentNotNull(head, "head"); 52 Safe.ArgumentNotNull(head, "head");
53 53
54 that.On(() => head.On(cleanup), PromiseEventType.Cancelled); 54 that.On(() => head.On(cleanup), PromiseEventType.Cancelled);
55 55
56 return that; 56 return that;
57 } 57 }
58 58
59 public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult,T> callback) { 59 /// <summary>
60 /// Adds a cancellation point to the chain of promises. When a cancellation request reaches the cancellation point the operation is
61 /// cancelled immediatelly, and the request is passed towards. If the operation at the higher level can not be cancelled is't result
62 /// will be collected with <paramref name="cleanup"/> callback.
63 /// </summary>
64 /// <typeparam name="T">The type of the promise result.</typeparam>
65 /// <param name="that">The promise to which the cancellation point should be attached.</param>
66 /// <param name="cleanup">The callback which is used to cleanup the result of the operation if the cancellation point is cancelled already.</param>
67 /// <returns>The promise</returns>
68 public static IPromise<T> CancellationPoint<T>(this IPromise<T> that, Action<T> cleanup) {
69 var meduim = new Promise<T>();
70
71 that.On(meduim.Resolve, meduim.Reject, meduim.CancelOperation);
72
73 meduim.CancellationRequested(that.Cancel);
74 meduim.CancellationRequested(meduim.CancelOperation);
75
76 if (cleanup != null)
77 meduim.On((Action<T>)null, null, (e) => {
78 that.On(cleanup);
79 });
80
81 return meduim;
82 }
83
84 public static AsyncCallback AsyncCallback<T>(this Promise<T> that, Func<IAsyncResult, T> callback) {
60 Safe.ArgumentNotNull(that, "that"); 85 Safe.ArgumentNotNull(that, "that");
61 Safe.ArgumentNotNull(callback, "callback"); 86 Safe.ArgumentNotNull(callback, "callback");
62 var op = TraceContext.Instance.CurrentOperation; 87 var op = TraceContext.Instance.CurrentOperation;
63 return ar => { 88 return ar => {
64 TraceContext.Instance.EnterLogicalOperation(op,false); 89 TraceContext.Instance.EnterLogicalOperation(op, false);
65 try { 90 try {
66 that.Resolve(callback(ar)); 91 that.Resolve(callback(ar));
67 } catch (Exception err) { 92 } catch (Exception err) {
68 that.Reject(err); 93 that.Reject(err);
69 } finally { 94 } finally {
74 99
75 static void CancelByTimeoutCallback(object cookie) { 100 static void CancelByTimeoutCallback(object cookie) {
76 ((ICancellable)cookie).Cancel(new TimeoutException()); 101 ((ICancellable)cookie).Cancel(new TimeoutException());
77 } 102 }
78 103
79 /// <summary> 104 /// <summary>
80 /// Cancells promise after the specified timeout is elapsed. 105 /// Cancells promise after the specified timeout is elapsed.
81 /// </summary> 106 /// </summary>
82 /// <param name="that">The promise to cancel on timeout.</param> 107 /// <param name="that">The promise to cancel on timeout.</param>
83 /// <param name="milliseconds">The timeout in milliseconds.</param> 108 /// <param name="milliseconds">The timeout in milliseconds.</param>
84 /// <typeparam name="TPromise">The 1st type parameter.</typeparam> 109 /// <typeparam name="TPromise">The 1st type parameter.</typeparam>
110 medium.Resolve(); 135 medium.Resolve();
111 return medium; 136 return medium;
112 } 137 }
113 138
114 medium.On(() => { 139 medium.On(() => {
115 foreach(var p2 in that) 140 foreach (var p2 in that)
116 p2.Cancel(); 141 p2.Cancel();
117 }, PromiseEventType.ErrorOrCancel); 142 }, PromiseEventType.ErrorOrCancel);
118 143
119 foreach (var p in that) 144 foreach (var p in that)
120 p.On( 145 p.On(
146 int errors = 0; 171 int errors = 0;
147 var medium = new Promise<T[]>(); 172 var medium = new Promise<T[]>();
148 var results = new T[that.Count]; 173 var results = new T[that.Count];
149 174
150 medium.On(() => { 175 medium.On(() => {
151 foreach(var p2 in that) 176 foreach (var p2 in that)
152 p2.Cancel(); 177 p2.Cancel();
153 }, PromiseEventType.ErrorOrCancel); 178 }, PromiseEventType.ErrorOrCancel);
154 179
155 int i = 0; 180 int i = 0;
156 foreach (var p in that) { 181 foreach (var p in that) {
214 return Then(that, success, null, null); 239 return Then(that, success, null, null);
215 } 240 }
216 241
217 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error, Func<Exception, T2> cancel) { 242 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error, Func<Exception, T2> cancel) {
218 Safe.ArgumentNotNull(that, "that"); 243 Safe.ArgumentNotNull(that, "that");
219 var d = new FuncTask<T,T2>(success, error, cancel, false); 244 var d = new FuncTask<T, T2>(success, error, cancel, false);
220 that.On(d.Resolve, d.Reject, d.CancelOperation); 245 that.On(d.Resolve, d.Reject, d.CancelOperation);
221 d.CancellationRequested(that.Cancel); 246 d.CancellationRequested(that.Cancel);
222 return d; 247 return d;
248 }
249
250 public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success, Func<Exception, T> error, Func<Exception, T> cancel) {
251 Safe.ArgumentNotNull(that, "that");
252 var d = new FuncTask<T, T>(
253 x => {
254 success(x);
255 return x;
256 },
257 error,
258 cancel,
259 false
260 );
261 that.On(d.Resolve, d.Reject, d.CancelOperation);
262 d.CancellationRequested(that.Cancel);
263 return d;
264 }
265
266 public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success, Func<Exception, T> error) {
267 return Then(that, success, error, null);
268 }
269
270 public static IPromise<T> Then<T>(this IPromise<T> that, Action<T> success) {
271 return Then(that, success, null, null);
223 } 272 }
224 273
225 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error) { 274 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success, Func<Exception, T2> error) {
226 return Then(that, success, error, null); 275 return Then(that, success, error, null);
227 } 276 }
228 277
229 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success) { 278 public static IPromise<T2> Then<T, T2>(this IPromise<T> that, Func<T, T2> success) {
230 return Then(that, success, null, null); 279 return Then(that, success, null, null);
231 } 280 }
232 281
282 public static IPromise<T> Always<T>(this IPromise<T> that, Action handler) {
283 Func<Exception, T> errorOrCancel;
284 if (handler != null)
285 errorOrCancel = e => {
286 handler();
287 throw new PromiseTransientException(e);
288 };
289 else
290 errorOrCancel = null;
291
292 return Then(
293 that,
294 x => {
295 handler();
296 return x;
297 },
298 errorOrCancel,
299 errorOrCancel);
300 }
301
302 public static IPromise Always(this IPromise that, Action handler) {
303 Action<Exception> errorOrCancel;
304 if (handler != null)
305 errorOrCancel = e => {
306 handler();
307 throw new PromiseTransientException(e);
308 };
309 else
310 errorOrCancel = null;
311
312 return Then(
313 that,
314 handler,
315 errorOrCancel,
316 errorOrCancel);
317 }
318
319 public static IPromise Error(this IPromise that, Action<Exception> handler, bool handleCancellation) {
320 Action<Exception> errorOrCancel;
321 if (handler != null)
322 errorOrCancel = e => {
323 handler(e);
324 throw new PromiseTransientException(e);
325 };
326 else
327 errorOrCancel = null;
328
329 return Then(that, null, errorOrCancel, handleCancellation ? errorOrCancel : null);
330 }
331
332 public static IPromise Error(this IPromise that, Action<Exception> handler) {
333 return Error(that, handler, false);
334 }
335
336 public static IPromise<T> Error<T>(this IPromise<T> that, Action<Exception> handler, bool handleCancellation) {
337 Func<Exception, T> errorOrCancel;
338 if (handler != null)
339 errorOrCancel = e => {
340 handler(e);
341 throw new PromiseTransientException(e);
342 };
343 else
344 errorOrCancel = null;
345
346 return Then(that, null, errorOrCancel, handleCancellation ? errorOrCancel : null);
347 }
348
349 public static IPromise<T> Error<T>(this IPromise<T> that, Action<Exception> handler) {
350 return Error(that, handler, false);
351 }
352
233 #region chain traits 353 #region chain traits
234 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception,IPromise> error, Func<Exception,IPromise> cancel) { 354 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception, IPromise> error, Func<Exception, IPromise> cancel) {
235 Safe.ArgumentNotNull(that, "that"); 355 Safe.ArgumentNotNull(that, "that");
236 356
237 var d = new ActionChainTask(success, error, cancel, false); 357 var d = new ActionChainTask(success, error, cancel, false);
238 that.On(d.Resolve, d.Reject, d.CancelOperation); 358 that.On(d.Resolve, d.Reject, d.CancelOperation);
239 d.CancellationRequested(that.Cancel); 359 d.CancellationRequested(that.Cancel);
240 return d; 360 return d;
241 } 361 }
242 362
243 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception,IPromise> error) { 363 public static IPromise Chain(this IPromise that, Func<IPromise> success, Func<Exception, IPromise> error) {
244 return Chain(that, success, error, null); 364 return Chain(that, success, error, null);
245 } 365 }
246 366
247 public static IPromise Chain(this IPromise that, Func<IPromise> success) { 367 public static IPromise Chain(this IPromise that, Func<IPromise> success) {
248 return Chain(that, success, null, null); 368 return Chain(that, success, null, null);
266 return Chain(that, success, null, null); 386 return Chain(that, success, null, null);
267 } 387 }
268 388
269 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel) { 389 public static IPromise<T2> Chain<T, T2>(this IPromise<T> that, Func<T, IPromise<T2>> success, Func<Exception, IPromise<T2>> error, Func<Exception, IPromise<T2>> cancel) {
270 Safe.ArgumentNotNull(that, "that"); 390 Safe.ArgumentNotNull(that, "that");
271 var d = new FuncChainTask<T,T2>(success, error, cancel, false); 391 var d = new FuncChainTask<T, T2>(success, error, cancel, false);
272 that.On(d.Resolve, d.Reject, d.CancelOperation); 392 that.On(d.Resolve, d.Reject, d.CancelOperation);
273 if (success != null) 393 if (success != null)
274 d.CancellationRequested(that.Cancel); 394 d.CancellationRequested(that.Cancel);
275 return d; 395 return d;
276 } 396 }
283 return Chain(that, success, null, null); 403 return Chain(that, success, null, null);
284 } 404 }
285 405
286 #endregion 406 #endregion
287 407
288 408
289 #if NET_4_5 409 #if NET_4_5
290 410
291 public static PromiseAwaiter<T> GetAwaiter<T>(this IPromise<T> that) { 411 public static PromiseAwaiter<T> GetAwaiter<T>(this IPromise<T> that) {
292 Safe.ArgumentNotNull(that, "that"); 412 Safe.ArgumentNotNull(that, "that");
293 413
294 return new PromiseAwaiter<T>(that); 414 return new PromiseAwaiter<T>(that);
295 } 415 }
296 416
297 #endif 417 #endif
298 } 418 }
299 } 419 }
300 420