javascript - 等待 JavaScript 中的变量
问题描述
我正在使用nodeJS。我想等待对象内的属性变为真,然后继续执行代码。
这是我的代码的样子:
export async function createRun() {
try {
let shared = { url: "", device: "", finished: new Promise(() => {}) };
const browser = await launch();
const page = await browser.newPage();
await page.setDefaultNavigationTimeout(0);
await page.setBypassCSP(true);
await page.exposeFunction(
"onMessageReceivedEvent",
async (e: { type: string; data: Message }) => {
if (e.data === "finished") {
shared.finished = ;
}
}
);
const listenFor = (type: string) => {
return page.evaluateOnNewDocument((type: any) => {
window.addEventListener(type, (e) => {
// @ts-ignore
window.onMessageReceivedEvent({ type, data: e.data });
});
}, type);
};
await listenFor("message");
console.log('before');
// wait for shared.finished to become true
// continue execution
console.log('after')
}
如何实施?提前致谢!
解决方案
好的,现在有了所有详细信息,可以回答您的问题。
得到结果认为暴露的函数可能 - 乍一看 - 会阻止 Promise 的使用。但是您可以为此使用闭包。
因此,您在 a 中创建回调函数new Promise
,并将其分配给该变量之外的变量。在您的回调中,您可以在满足resolve
您的条件时做出承诺e.data === "finished"
。
let onMessageReceivedEventCallback;
const messageReceived = new Promise((resolve, reject) => {
onMessageReceivedEventCallback = (e: { type: string; data: Message }) => {
if (e.data === "finished") {
resolve();
}
// TODO you might want to reject in case an error occurs here, so that your application won't halt
}
// TODO if there is no specific error case then you might reject here after a given timeout
// setTimout(() => reject(new Error("Timeout")), 1000);
})
然后你将该函数传递给你的page.exposeFunction
,然后你await messageReceived
用来等待该承诺得到解决。
export async function createRun() {
try {
let shared = { url: "", device: "" };
const browser = await launch();
const page = await browser.newPage();
await page.setDefaultNavigationTimeout(0);
await page.setBypassCSP(true);
let onMessageReceivedEventCallback;
const messageReceived = new Promise((resolve, reject) => {
onMessageReceivedEventCallback = (e: { type: string; data: Message }) => {
if (e.data === "finished") {
resolve();
}
// TODO you might want to reject in case an error occurs here, so that your application won't halt
}
// TODO if there is no specific error case then you might reject here after a given timeout
// setTimout(() => reject(new Error("Timeout")), 1000);
})
await page.exposeFunction(
"onMessageReceivedEvent", onMessageReceivedEventCallback
);
const listenFor = (type: string) => {
return page.evaluateOnNewDocument((type: any) => {
window.addEventListener(type, (e) => {
// @ts-ignore
window.onMessageReceivedEvent({ type, data: e.data });
});
}, type);
};
await listenFor("message");
console.log('before');
await messageReceived;
console.log('after')
}
要回答您最初的问题,技术上可以使用 getter、setter 或 Proxy 来实现类似的目标。在下文中,我将展示如何使用代理来完成类似的操作。但请注意,我强烈反对使用它。它只是掩盖了代码中发生的事情,我无法想象一个真正有意义的用例。
function createWaitAbleProperties(initialObject = {}, timeout = 2000) {
function initProperty(obj, name) {
obj.properties[name] = {}
// utelizing a defere pattern which is not recommended
// it is not as bas as the regular one due to the timeout but it is still bad
obj.properties[name].promise = new Promise((resolve, reject) => {
obj.properties[name].resolve = resolve
setTimeout(() => reject(new Error('timeout for ' + name)), timeout);
})
}
return new Proxy(initialObject, {
properties: {},
get: function(obj, prop) {
let match;
if (match = prop.match(/^(.*)Promise$/)) {
if (!this.properties[match[1]]) {
initProperty(this, match[1])
}
return this.properties[match[1]].promise
} else {
return this.properties[prop]?.value
}
},
set: function(obj, prop, value) {
if (!this.properties[prop]) {
initProperty(this, prop)
}
this.properties[prop].resolve()
this.properties[prop].value = value
}
});
}
async function run() {
const observer = createWaitAbleProperties()
observer.value2 = 200
setTimeout(() => {
observer.value1 = 100
}, 1000)
await observer.value1Promise
await observer.value2Promise
console.log('finished', observer.value1, observer.value2)
}
run()
推荐阅读
- javascript - 在点击而不是悬停时显示下拉菜单
- c# - 尝试使用 C# 在 Windows 注册表中设置 DWORD 值时出错
- operating-system - automating a chain of shell commands with os.popen Python and 'sudo' is not recognized
- javascript - VSCode colours are changing
- javascript - Javascript将多行缓冲区的条码扫描仪输出转换为数组或json
- mongodb - DocumentDb Compound Query really slow for Date
- r - Applying lm() using sapply or lapply
- php - .htaccess mod_rewrite on multiple PHP files issue
- java - JBPM 7 生成的 XML 中的递归节点
- python - 在 MacOS 上使用 PyInstaller 加载 Python 库时出错