在脚本标签中使用 Promises 不起作用?
Using Promises in script tag not working?
我的以下代码用于使用承诺在 DOM 中附加脚本。 (以下所有代码都在 iframe 内执行,用于 A 帧技术,我的代码是使用 Google Blockly[基于块的编码] 生成的)
export const appendScript = async({
src,
aframeWindow,
code,
id
},
doc,
callback,
) =>
new Promise(resolve => {
const startDate = new Date();
const script = doc.createElement('script');
if (src) script.src = src;
if (code) {
script.text = code;
}
if (id) {
script.id = id;
}
doc.head.appendChild(script);
if (callback) callback();
if (code) {
if (callback) {
callback();
}
console.log(aframeWindow.onGreenPlayButtonClicked, "===="); // undefined when code string contains await outside ongreenplaybuttonclicked fn
resolve('resolved');
} else {
script.addEventListener('load', () => {
const endDate = new Date();
const seconds = (endDate.getTime() - startDate.getTime()) / 1000;
console.log('script loaded: ', src, `took ${seconds} to load`);
resolve('resolve2');
});
}
});
下面的脚本是我调用 appendscript 的函数。
const callAppendScript = async code => {
const CODE_VERSION = aframeWindow.CODE_VERSION;
code = `
async function main(inPlayMode) {
let CURRENT_CODE_VERSION = CODE_VERSION;
${code};
}
main();
`;
let x = await appendScript({
code,
aframeWindow,
id: 'code'
},
aframeWindow.document,
);
}
callAppendScript(code);
我的代码字符串 1 生成:(不起作用)
async function main(inPlayMode) {
let CURRENT_CODE_VERSION = !inPlayMode ? 0 : window.CODE_VERSION;
var greeting;
greeting = await HatchTranslateEngine.translate(`Hello`, 'en'); //async
window.onGreenPlayButtonClicked = async function onGreenPlayButtonClicked() {
await MinecraftAvatar.speakSound(greeting, true)
};
}
main();
我的代码字符串 2 生成:(有效)
async function main(inPlayMode) {
let CURRENT_CODE_VERSION = !inPlayMode ? 0 : window.CODE_VERSION;
var greeting;
greeting = Hatch.convert(`Hello`, 'jp'); //syncrhonous
window.onGreenPlayButtonClicked = async function onGreenPlayButtonClicked() {
await MinecraftAvatar.speakSound(greeting, true)
};
}
main();
我生成的代码字符串 3:(仍然有效)
async function main(inPlayMode) {
let CURRENT_CODE_VERSION = !inPlayMode ? 0 : window.CODE_VERSION;
var greeting;
window.onGreenPlayButtonClicked = async function onGreenPlayButtonClicked() {
greeting = await HatchTranslateEngine.translate(`Hello`, 'en'); //async this still works (inside playbtn)
await MinecraftAvatar.speakSound(greeting, true)
};
}
main();
每当我点击播放按钮时,callAppendScript(code)
就会被执行,当它执行时,
对于 代码字符串 1,它在 aframeWindow.onGreenPlayButtonClicked
中给出 undefined (不正确)
对于 code string 2,它给了我 onGreenPlayButtonClicked 中 aframeWindow.onGreenPlayButtonClicked
的函数签名(正确)
那么,为什么它对案例 1 不起作用,我尝试了所有方法但无法弄清楚。我只发现对于 onGreenPlayButtonClicked 之外的任何 await
关键字,我得到 aframeWindow.onGreenPlayButtonClicked
位于 appendScript
函数内。
谢谢
appendScript
中没有任何内容等待 main()
调用 returns 的承诺。如果您正在异步初始化 onGreenPlayButtonClicked
,它不会在附加脚本元素后立即可用。
我建议你试试
const callAppendScript = async code => {
const CODE_VERSION = aframeWindow.CODE_VERSION;
code = `
async function main(inPlayMode) {
let CURRENT_CODE_VERSION = CODE_VERSION;
${code};
}
// no main() call here
`;
await appendScript({
code,
aframeWindow,
id: 'code'
}, aframeWindow.document);
console.log(aframeWindow.onGreenPlayButtonClicked, "before");
await main();
//^^^^^^^^^^^^
console.log(aframeWindow.onGreenPlayButtonClicked, "after");
}
我的以下代码用于使用承诺在 DOM 中附加脚本。 (以下所有代码都在 iframe 内执行,用于 A 帧技术,我的代码是使用 Google Blockly[基于块的编码] 生成的)
export const appendScript = async({
src,
aframeWindow,
code,
id
},
doc,
callback,
) =>
new Promise(resolve => {
const startDate = new Date();
const script = doc.createElement('script');
if (src) script.src = src;
if (code) {
script.text = code;
}
if (id) {
script.id = id;
}
doc.head.appendChild(script);
if (callback) callback();
if (code) {
if (callback) {
callback();
}
console.log(aframeWindow.onGreenPlayButtonClicked, "===="); // undefined when code string contains await outside ongreenplaybuttonclicked fn
resolve('resolved');
} else {
script.addEventListener('load', () => {
const endDate = new Date();
const seconds = (endDate.getTime() - startDate.getTime()) / 1000;
console.log('script loaded: ', src, `took ${seconds} to load`);
resolve('resolve2');
});
}
});
下面的脚本是我调用 appendscript 的函数。
const callAppendScript = async code => {
const CODE_VERSION = aframeWindow.CODE_VERSION;
code = `
async function main(inPlayMode) {
let CURRENT_CODE_VERSION = CODE_VERSION;
${code};
}
main();
`;
let x = await appendScript({
code,
aframeWindow,
id: 'code'
},
aframeWindow.document,
);
}
callAppendScript(code);
我的代码字符串 1 生成:(不起作用)
async function main(inPlayMode) {
let CURRENT_CODE_VERSION = !inPlayMode ? 0 : window.CODE_VERSION;
var greeting;
greeting = await HatchTranslateEngine.translate(`Hello`, 'en'); //async
window.onGreenPlayButtonClicked = async function onGreenPlayButtonClicked() {
await MinecraftAvatar.speakSound(greeting, true)
};
}
main();
我的代码字符串 2 生成:(有效)
async function main(inPlayMode) {
let CURRENT_CODE_VERSION = !inPlayMode ? 0 : window.CODE_VERSION;
var greeting;
greeting = Hatch.convert(`Hello`, 'jp'); //syncrhonous
window.onGreenPlayButtonClicked = async function onGreenPlayButtonClicked() {
await MinecraftAvatar.speakSound(greeting, true)
};
}
main();
我生成的代码字符串 3:(仍然有效)
async function main(inPlayMode) {
let CURRENT_CODE_VERSION = !inPlayMode ? 0 : window.CODE_VERSION;
var greeting;
window.onGreenPlayButtonClicked = async function onGreenPlayButtonClicked() {
greeting = await HatchTranslateEngine.translate(`Hello`, 'en'); //async this still works (inside playbtn)
await MinecraftAvatar.speakSound(greeting, true)
};
}
main();
每当我点击播放按钮时,callAppendScript(code)
就会被执行,当它执行时,
对于 代码字符串 1,它在 aframeWindow.onGreenPlayButtonClicked
中给出 undefined (不正确)
对于 code string 2,它给了我 onGreenPlayButtonClicked 中 aframeWindow.onGreenPlayButtonClicked
的函数签名(正确)
那么,为什么它对案例 1 不起作用,我尝试了所有方法但无法弄清楚。我只发现对于 onGreenPlayButtonClicked 之外的任何 await
关键字,我得到 aframeWindow.onGreenPlayButtonClicked
位于 appendScript
函数内。
谢谢
appendScript
中没有任何内容等待 main()
调用 returns 的承诺。如果您正在异步初始化 onGreenPlayButtonClicked
,它不会在附加脚本元素后立即可用。
我建议你试试
const callAppendScript = async code => {
const CODE_VERSION = aframeWindow.CODE_VERSION;
code = `
async function main(inPlayMode) {
let CURRENT_CODE_VERSION = CODE_VERSION;
${code};
}
// no main() call here
`;
await appendScript({
code,
aframeWindow,
id: 'code'
}, aframeWindow.document);
console.log(aframeWindow.onGreenPlayButtonClicked, "before");
await main();
//^^^^^^^^^^^^
console.log(aframeWindow.onGreenPlayButtonClicked, "after");
}