Mercurial > pub > ImplabNet
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 |