@@ -149,55 +149,87 @@ var tryExamplesGlobalMinHeight = 0;
149
149
*/
150
150
var tryExamplesConfigLoaded = false ;
151
151
152
- window . loadTryExamplesConfig = async ( configFilePath ) => {
153
- if ( tryExamplesConfigLoaded ) {
154
- return ;
155
- }
156
- try {
157
- // Add a timestamp as query parameter to ensure a cached version of the
158
- // file is not used.
159
- const timestamp = new Date ( ) . getTime ( ) ;
160
- const configFileUrl = `${ configFilePath } ?cb=${ timestamp } ` ;
161
- const currentPageUrl = window . location . pathname ;
162
-
163
- const response = await fetch ( configFileUrl ) ;
164
- if ( ! response . ok ) {
165
- if ( response . status === 404 ) {
166
- // Try examples ignore file is not present.
167
- console . log ( "Optional try_examples config file not found." ) ;
168
- return ;
169
- }
170
- throw new Error ( `Error fetching ${ configFilePath } ` ) ;
171
- }
152
+ // A config loader with request deduplication + permanent caching
153
+ const ConfigLoader = ( ( ) => {
154
+ let configLoadPromise = null ;
172
155
173
- const data = await response . json ( ) ;
174
- if ( ! data ) {
156
+ const loadConfig = async ( configFilePath ) => {
157
+ if ( tryExamplesConfigLoaded ) {
175
158
return ;
176
159
}
177
160
178
- // Set minimum iframe height based on value in config file
179
- if ( data . global_min_height ) {
180
- tryExamplesGlobalMinHeight = parseInt ( data . global_min_height ) ;
161
+ // Return the existing promise if the request is in progress, as we
162
+ // don't want to make multiple requests for the same file. This
163
+ // can happen if there are several try_examples directives on the
164
+ // same page.
165
+ if ( configLoadPromise ) {
166
+ return configLoadPromise ;
181
167
}
182
168
183
- // Disable interactive examples if file matches one of the ignore patterns
184
- // by hiding try_examples_buttons.
185
- Patterns = data . ignore_patterns ;
186
- for ( let pattern of Patterns ) {
187
- let regex = new RegExp ( pattern ) ;
188
- if ( regex . test ( currentPageUrl ) ) {
189
- var buttons = document . getElementsByClassName ( "try_examples_button" ) ;
190
- for ( var i = 0 ; i < buttons . length ; i ++ ) {
191
- buttons [ i ] . classList . add ( "hidden" ) ;
169
+ // Create and cache the promise for the config request
170
+ configLoadPromise = ( async ( ) => {
171
+ try {
172
+ // Add a timestamp as query parameter to ensure a cached version of the
173
+ // file is not used.
174
+ const timestamp = new Date ( ) . getTime ( ) ;
175
+ const configFileUrl = `${ configFilePath } ?cb=${ timestamp } ` ;
176
+ const currentPageUrl = window . location . pathname ;
177
+
178
+ const response = await fetch ( configFileUrl ) ;
179
+ if ( ! response . ok ) {
180
+ if ( response . status === 404 ) {
181
+ console . log ( "Optional try_examples config file not found." ) ;
182
+ return ;
183
+ }
184
+ throw new Error ( `Error fetching ${ configFilePath } ` ) ;
185
+ }
186
+
187
+ const data = await response . json ( ) ;
188
+ if ( ! data ) {
189
+ return ;
190
+ }
191
+
192
+ // Set minimum iframe height based on value in config file
193
+ if ( data . global_min_height ) {
194
+ tryExamplesGlobalMinHeight = parseInt ( data . global_min_height ) ;
195
+ }
196
+
197
+ // Disable interactive examples if file matches one of the ignore patterns
198
+ // by hiding try_examples_buttons.
199
+ Patterns = data . ignore_patterns ;
200
+ for ( let pattern of Patterns ) {
201
+ let regex = new RegExp ( pattern ) ;
202
+ if ( regex . test ( currentPageUrl ) ) {
203
+ var buttons = document . getElementsByClassName (
204
+ "try_examples_button" ,
205
+ ) ;
206
+ for ( var i = 0 ; i < buttons . length ; i ++ ) {
207
+ buttons [ i ] . classList . add ( "hidden" ) ;
208
+ }
209
+ break ;
210
+ }
192
211
}
193
- break ;
212
+ } catch ( error ) {
213
+ console . error ( error ) ;
214
+ } finally {
215
+ tryExamplesConfigLoaded = true ;
194
216
}
195
- }
196
- } catch ( error ) {
197
- console . error ( error ) ;
198
- }
199
- tryExamplesConfigLoaded = true ;
200
- } ;
217
+ } ) ( ) ;
218
+
219
+ return configLoadPromise ;
220
+ } ;
221
+
222
+ return {
223
+ loadConfig,
224
+ // for testing/debugging only, could be removed
225
+ resetState : ( ) => {
226
+ tryExamplesConfigLoaded = false ;
227
+ configLoadPromise = null ;
228
+ } ,
229
+ } ;
230
+ } ) ( ) ;
231
+
232
+ window . loadTryExamplesConfig = ConfigLoader . loadConfig ;
201
233
202
234
window . toggleTryExamplesButtons = ( ) => {
203
235
/* Toggle visibility of TryExamples buttons. For use in console for debug
0 commit comments