1
+ /**
2
+ * @license
3
+ * Copyright Google Inc. All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.io/license
7
+ */
8
+
9
+ Zone . __load_patch ( 'fetch' , ( global : any , Zone : ZoneType , api : _ZonePrivate ) => {
10
+ const fetch = global [ 'fetch' ] ;
11
+ const ZoneAwarePromise = global . Promise ;
12
+ const symbolThenPatched = api . symbol ( 'thenPatched' ) ;
13
+ const fetchTaskScheduling = api . symbol ( 'fetchTaskScheduling' ) ;
14
+ const fetchTaskAborting = api . symbol ( 'fetchTaskAborting' ) ;
15
+ if ( typeof fetch !== 'function' ) {
16
+ return ;
17
+ }
18
+ const OriginalAbortController = global [ 'AbortController' ] ;
19
+ const supportAbort = typeof OriginalAbortController === 'function' ;
20
+ let abortNative : Function | null = null ;
21
+ if ( supportAbort ) {
22
+ global [ 'AbortController' ] = function ( ) {
23
+ const abortController = new OriginalAbortController ( ) ;
24
+ const signal = abortController . signal ;
25
+ signal . abortController = abortController ;
26
+ return abortController ;
27
+ } ;
28
+ abortNative = api . patchMethod (
29
+ OriginalAbortController . prototype , 'abort' ,
30
+ ( delegate : Function ) => ( self : any , args : any ) => {
31
+ if ( self . task ) {
32
+ return self . task . zone . cancelTask ( self . task ) ;
33
+ }
34
+ return delegate . apply ( self , args ) ;
35
+ } ) ;
36
+ }
37
+ const placeholder = function ( ) { } ;
38
+ global [ 'fetch' ] = function ( ) {
39
+ const args = Array . prototype . slice . call ( arguments ) ;
40
+ const options = args . length > 1 ? args [ 1 ] : null ;
41
+ const signal = options && options . signal ;
42
+ return new Promise ( ( res , rej ) => {
43
+ const task = Zone . current . scheduleMacroTask (
44
+ 'fetch' , placeholder , args ,
45
+ ( ) => {
46
+ let fetchPromise ;
47
+ let zone = Zone . current ;
48
+ try {
49
+ ( zone as any ) [ fetchTaskScheduling ] = true ;
50
+ fetchPromise = fetch . apply ( this , args ) ;
51
+ } catch ( error ) {
52
+ rej ( error ) ;
53
+ return ;
54
+ } finally {
55
+ ( zone as any ) [ fetchTaskScheduling ] = false ;
56
+ }
57
+
58
+ if ( ! ( fetchPromise instanceof ZoneAwarePromise ) ) {
59
+ let ctor = fetchPromise . constructor ;
60
+ if ( ! ctor [ symbolThenPatched ] ) {
61
+ api . patchThen ( ctor ) ;
62
+ }
63
+ }
64
+ fetchPromise . then (
65
+ ( resource : any ) => {
66
+ if ( task . state !== 'notScheduled' ) {
67
+ task . invoke ( ) ;
68
+ }
69
+ res ( resource ) ;
70
+ } ,
71
+ ( error : any ) => {
72
+ if ( task . state !== 'notScheduled' ) {
73
+ task . invoke ( ) ;
74
+ }
75
+ rej ( error ) ;
76
+ } ) ;
77
+ } ,
78
+ ( ) => {
79
+ if ( ! supportAbort ) {
80
+ rej ( 'No AbortController supported, can not cancel fetch' ) ;
81
+ return ;
82
+ }
83
+ if ( signal && signal . abortController && ! signal . aborted &&
84
+ typeof signal . abortController . abort === 'function' && abortNative ) {
85
+ try {
86
+ ( Zone . current as any ) [ fetchTaskAborting ] = true ;
87
+ abortNative . call ( signal . abortController ) ;
88
+ } finally {
89
+ ( Zone . current as any ) [ fetchTaskAborting ] = false ;
90
+ }
91
+ } else {
92
+ rej ( 'cancel fetch need a AbortController.signal' ) ;
93
+ }
94
+ } ) ;
95
+ if ( signal && signal . abortController ) {
96
+ signal . abortController . task = task ;
97
+ }
98
+ } ) ;
99
+ } ;
100
+ } ) ;
0 commit comments