217
217
* @returns {Promise } The newly created promise.
218
218
*/
219
219
function $QProvider ( ) {
220
-
220
+ var errorOnUnhandledRejections = true ;
221
221
this . $get = [ '$rootScope' , '$exceptionHandler' , function ( $rootScope , $exceptionHandler ) {
222
222
return qFactory ( function ( callback ) {
223
223
$rootScope . $evalAsync ( callback ) ;
224
- } , $exceptionHandler ) ;
224
+ } , $exceptionHandler , errorOnUnhandledRejections ) ;
225
225
} ] ;
226
+
227
+ /**
228
+ * @ngdoc method
229
+ * @name $qProvider#errorOnUnhandledRejections
230
+ * @kind function
231
+ *
232
+ * @description
233
+ * Retrieves or overrides on wheter to generate an error when a rejected promise is not handled.
234
+ *
235
+ * @param {boolean= } value Wheter to generate an error when a rejected promise is not handled.
236
+ * @returns {boolean|ng.$qProvider } Current value when called without a new value or self for
237
+ * chaining otherwise.
238
+ */
239
+ this . errorOnUnhandledRejections = function ( value ) {
240
+ if ( isDefined ( value ) ) {
241
+ errorOnUnhandledRejections = value ;
242
+ return this ;
243
+ } else {
244
+ return errorOnUnhandledRejections ;
245
+ }
246
+ } ;
226
247
}
227
248
228
249
function $$QProvider ( ) {
250
+ var errorOnUnhandledRejections = true ;
229
251
this . $get = [ '$browser' , '$exceptionHandler' , function ( $browser , $exceptionHandler ) {
230
252
return qFactory ( function ( callback ) {
231
253
$browser . defer ( callback ) ;
232
- } , $exceptionHandler ) ;
254
+ } , $exceptionHandler , errorOnUnhandledRejections ) ;
233
255
} ] ;
256
+
257
+ this . errorOnUnhandledRejections = function ( value ) {
258
+ if ( isDefined ( value ) ) {
259
+ errorOnUnhandledRejections = value ;
260
+ return this ;
261
+ } else {
262
+ return errorOnUnhandledRejections ;
263
+ }
264
+ } ;
234
265
}
235
266
236
267
/**
@@ -239,10 +270,14 @@ function $$QProvider() {
239
270
* @param {function(function) } nextTick Function for executing functions in the next turn.
240
271
* @param {function(...*) } exceptionHandler Function into which unexpected exceptions are passed for
241
272
* debugging purposes.
273
+ @ param {=boolean} errorOnUnhandledRejections Whether an error should be generated on unhandled
274
+ * promises rejections.
242
275
* @returns {object } Promise manager.
243
276
*/
244
- function qFactory ( nextTick , exceptionHandler ) {
277
+ function qFactory ( nextTick , exceptionHandler , errorOnUnhandledRejections ) {
245
278
var $qMinErr = minErr ( '$q' , TypeError ) ;
279
+ var queueSize = 0 ;
280
+ var checkQueue = [ ] ;
246
281
247
282
/**
248
283
* @ngdoc method
@@ -307,28 +342,62 @@ function qFactory(nextTick, exceptionHandler) {
307
342
pending = state . pending ;
308
343
state . processScheduled = false ;
309
344
state . pending = undefined ;
310
- for ( var i = 0 , ii = pending . length ; i < ii ; ++ i ) {
311
- deferred = pending [ i ] [ 0 ] ;
312
- fn = pending [ i ] [ state . status ] ;
313
- try {
314
- if ( isFunction ( fn ) ) {
315
- deferred . resolve ( fn ( state . value ) ) ;
316
- } else if ( state . status === 1 ) {
317
- deferred . resolve ( state . value ) ;
318
- } else {
319
- deferred . reject ( state . value ) ;
345
+ try {
346
+ for ( var i = 0 , ii = pending . length ; i < ii ; ++ i ) {
347
+ state . pur = true ;
348
+ deferred = pending [ i ] [ 0 ] ;
349
+ fn = pending [ i ] [ state . status ] ;
350
+ try {
351
+ if ( isFunction ( fn ) ) {
352
+ deferred . resolve ( fn ( state . value ) ) ;
353
+ } else if ( state . status === 1 ) {
354
+ deferred . resolve ( state . value ) ;
355
+ } else {
356
+ deferred . reject ( state . value ) ;
357
+ }
358
+ } catch ( e ) {
359
+ deferred . reject ( e ) ;
360
+ exceptionHandler ( e ) ;
320
361
}
321
- } catch ( e ) {
322
- deferred . reject ( e ) ;
323
- exceptionHandler ( e ) ;
362
+ }
363
+ } finally {
364
+ -- queueSize ;
365
+ if ( queueSize === 0 ) {
366
+ nextTick ( processChecksFn ( ) ) ;
367
+ }
368
+ }
369
+ }
370
+
371
+ function processChecks ( ) {
372
+ while ( ! queueSize && checkQueue . length ) {
373
+ var toCheck = checkQueue . shift ( ) ;
374
+ if ( errorOnUnhandledRejections && ! toCheck . pur ) {
375
+ toCheck . pur = true ;
376
+ var errorMessage = 'Possibly unhandled rejection: ' + toDebugString ( toCheck . value ) ;
377
+ exceptionHandler ( errorMessage ) ;
324
378
}
325
379
}
326
380
}
327
381
382
+ function processChecksFn ( ) {
383
+ return function ( ) { processChecks ( ) ; } ;
384
+ }
385
+
386
+ function processQueueFn ( state ) {
387
+ return function ( ) { processQueue ( state ) ; } ;
388
+ }
389
+
328
390
function scheduleProcessQueue ( state ) {
391
+ if ( ! state . pending && state . status === 2 && ! state . pur ) {
392
+ if ( queueSize === 0 && checkQueue . length === 0 ) {
393
+ nextTick ( processChecksFn ( ) ) ;
394
+ }
395
+ checkQueue . push ( state ) ;
396
+ }
329
397
if ( state . processScheduled || ! state . pending ) return ;
330
398
state . processScheduled = true ;
331
- nextTick ( function ( ) { processQueue ( state ) ; } ) ;
399
+ ++ queueSize ;
400
+ nextTick ( processQueueFn ( state ) ) ;
332
401
}
333
402
334
403
function Deferred ( ) {
0 commit comments