I’m trying to create an application following the architectural model present on the implementation of OneSignal’s Web Push applications.
Basically, OneSignal asks its user to add two JavaScript codes at the end of the page:
<script src="https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.page.js" defer></script>
<script>
window.OneSignalDeferred = window.OneSignalDeferred || [];
OneSignalDeferred.push(function(OneSignal) {
OneSignal.init({
appId: "YOUR_ONESIGNAL_APP_ID",
});
});
</script>
The first script refers to OneSignalSDK.page.js
, which is nothing more than a simple command responsible for adding another script inside the <head>
tag.
The second one, seems that he uses a existing commands within the script that was imported within the <head>
tag, in order to make it global through the window
variable:
window.OneSignalDeferred = window.OneSignalDeferred || [];
So that he can then use its methods and functions:
OneSignalDeferred.push(...);
To achieve this type of architectural model, I started by creating my own script that is usually added at the end of my HTML page:
<script src="./StackOverflowSDK.page.js" defer></script>
<script>
window.StackOverflowDeferred = window.StackOverflowDeferred || [];
console.log('StackOverflowDeferred: ', StackOverflowDeferred);
</script>
The code below is my StackOverflowSDK.page.js
, which is responsible for loading another JavaScript file within the <head>
tag:
(() => {
"use strict";
function importSDK(numberVersion){
var s = document.createElement('script');
s.defer = true;
s.src = "http://localhost/StackOverflow/StackOverflowSDK.page.es6.js?v=".concat(numberVersion);
document.head.appendChild(s);
}
importSDK(10001);
})();
Importing the above code works correctly, and the StackOverflowSDK.page.es6.js
script is implemented inside the <head>
tag perfectly.
The code below presents the StackOverflowSDK.page.es6.js
file:
(() => {
class StackClass {
static init(e){
//....
}
}
window.StackOverflowDeferred = StackClass;
})();
The problem is that the command window.StackOverflowDeferred = window.StackOverflowDeferred || [];
returns an empty array instead of a StackClass
class reference.
How to solve this problem?
2
Answers
It’s a pattern I personally recognize from GA or GTM, the idea is to have an array-like interface (usually just the
push
method) and to default back to an array before the script is loaded. Once the script is fully loaded, you initialize the actual instance with what was in that variable if it exists.Essentially, you don’t know whether you have the fully-loaded version or not, but it doesn’t matter.
// SomeSDK.page.js
If you absolutely need to have the actual variable, then just load your script using
defer
and position it in the DOM after theSDK
.use the DOMContentLoaded event, which stipulates:
The old-school way, used by jQuery and libraries like it (which should not be necessary nowadays) can be found here:
https://www.npmjs.com/package/domready
or here:
https://gist.github.com/nathankleyn/613221
which essentially boils down to looping until a variable becomes available: