我有一个带有异步函数的模块,init()该函数被多次调用。但是,我只希望函数的效果init()触发一次,任何后续调用都应该等待最初的承诺解决。
这是我当前的代码。此示例中的错误是,第二次init()调用该函数时,由于脚本标记已经存在,因此会立即解决该问题。我想等待onload第一次调用时创建的脚本的回调init()。
let scriptExists = false;
// This function should only be called once
// Returns a mock script that calls onload after 1000ms
function addScript() {
const mockScript = {
onload: () => {}
};
setTimeout(() => mockScript.onload(), 1000);
return mockScript;
}
// Add script and wait for it to load
function init() {
return new Promise((resolve) => {
if (!scriptExists) {
const script = addScript();
scriptExists = true;
script.onload = resolve;
} else {
// TODO: This should only resolve if the script has loaded
resolve();
}
});
}
// Wait for the script to load, then add message
async function doSomethingNice() {
await init();
console.log("nocie");
}
// Wait for the script to load, then add message
async function doSomethingElse() {
await init();
console.log("something else");
}
doSomethingNice();
doSomethingElse();
Run Code Online (Sandbox Code Playgroud)
https://codesandbox.io/s/modest-cohen-9k4bf?file=/src/index.js
您可以设置您的init函数,使其只执行一次工作,并在后续调用中返回第一次的承诺:
let promise;
function init() {
if (!promise) {
promise = new Promise((resolve) => {
const script = document.createElement('script');
script.id = SCRIPT_ID;
script.onload = resolve;
script.type = 'text/javascript';
script.src = 'https://www.example.com/';
document.head.appendChild(script);
});
}
return promise;
}
Run Code Online (Sandbox Code Playgroud)