@@ -25,6 +25,7 @@ import {
2525import { selectURI } from "./selectURI.js" ;
2626
2727const backupFetch = maybe ( ( ) => fetch ) ;
28+ function noop ( ) { }
2829
2930export class BaseHttpLink extends ApolloLink {
3031 constructor ( linkOptions : HttpLink . Options = { } ) {
@@ -89,11 +90,29 @@ export class BaseHttpLink extends ApolloLink {
8990 ) ;
9091 }
9192
92- let controller : AbortController | undefined ;
93- if ( ! options . signal && typeof AbortController !== "undefined" ) {
94- controller = new AbortController ( ) ;
95- options . signal = controller . signal ;
93+ let controller : AbortController | undefined = new AbortController ( ) ;
94+ let cleanupController = ( ) => {
95+ controller = undefined ;
96+ } ;
97+ if ( options . signal ) {
98+ // in an ideal world we could use `AbortSignal.any` here, but
99+ // React Native uses https://github.com/mysticatea/abort-controller as
100+ // a polyfill for `AbortController`, and it does not support `AbortSignal.any`.
101+ const abort = controller . abort . bind ( controller ) ;
102+ options . signal . addEventListener ( "abort" , abort , { once : true } ) ;
103+ cleanupController = ( ) => {
104+ controller = undefined ;
105+ // on cleanup, we need to stop listening to `options.signal` to avoid memory leaks
106+ options . signal . removeEventListener ( "abort" , abort ) ;
107+ cleanupController = noop ;
108+ } ;
109+ // react native also does not support the addEventListener `signal` option
110+ // so we have to simulate that ourself
111+ controller . signal . addEventListener ( "abort" , cleanupController , {
112+ once : true ,
113+ } ) ;
96114 }
115+ options . signal = controller . signal ;
97116
98117 if ( useGETForQueries && ! isMutationOperation ( operation . query ) ) {
99118 options . method = "GET" ;
@@ -132,11 +151,11 @@ export class BaseHttpLink extends ApolloLink {
132151 }
133152 } )
134153 . then ( ( ) => {
135- controller = undefined ;
154+ cleanupController ( ) ;
136155 observer . complete ( ) ;
137156 } )
138157 . catch ( ( err ) => {
139- controller = undefined ;
158+ cleanupController ( ) ;
140159 observer . error ( err ) ;
141160 } ) ;
142161
0 commit comments