为了开发软件插件,我需要监听使用
因为
dispatchEvent
生成的事件,并在接收到此事件时执行一些操作。重要的是,在软件继续执行dispatchEvent
后的代码之前,我的操作应该完成。因为
dispatchEvent
是同步的,所以理论上应该是这样...不幸的是,我的操作是异步的(基本上我需要等待视频被搜索),在这种情况下,dispatchEvent
会在我的代码结束之前继续执行。当调用的函数是异步的时候,是否有可能也获得dispatchEvent
的同步行为?
示例:
我希望以下代码能够产生输出结果:Putting the clothes in the washing machine.
Machine started...
Machine ended...
Picking the washed clothes.
不幸的是,衣服在洗衣机结束之前被拿走了:
Putting the clothes in the washing machine.
Machine started...
Picking the washed clothes.
Machine ended...
我使用了这段代码:
var button = document.getElementById('button');
button.addEventListener('click', event => {
console.log("Putting the clothes in the washing machine.");
const machineResult = button.dispatchEvent(new CustomEvent('startmachine', {
'detail': {
timeProgram: 3000
}
}));
if (machineResult.defaultPrevented) {
console.log("Picking the dirty clothes.");
} else {
console.log("Picking the washed clothes.");
}
});
button.addEventListener('startmachine', async event => {
console.log("Machine started...");
await new Promise(r => setTimeout(r, event.detail.timeProgram));
console.log("Machine ended...");
});
<button id="button">Wash my clothes</button>
编辑:我发现了一个不太好的解决方案
由于看起来似乎不可能,我采用了另一种方法,不幸的是,它需要在代码dispatchEvent
后进行一些更改(由于我不负责代码的这部分,我更喜欢一种在dispatchEvent
之后不更改代码的方法)。
这个想法是在事件中添加一个数组,每个侦听器都可以放置一个异步函数。然后,在dispatchEvent
完成后,代码会执行此数组中的所有函数,并且如果有任何一个函数返回false
,则认为事件已被中止。
var button = document.getElementById('button');
button.addEventListener('click', async event => {
console.log("Putting the clothes in the washing machine.");
var listOfActions = [];
const machineResult = button.dispatchEvent(new CustomEvent('startmachine', { 'detail': {timeProgram: 3000, listOfActions: listOfActions} }));
results = await Promise.all(listOfActions.map(x => x()));
if (machineResult.defaultPrevented || !results.every(x => x != false)) { // Do not use == true or boolean to ensure returning nothing does not abort.
console.log("Picking the dirty clothes.");
} else {
console.log("Picking the washed clothes.");
}
});
button.addEventListener('startmachine', event => {
event.detail.listOfActions.push( async () => {
console.log(">>> Machine started...");
await new Promise(r => setTimeout(r, event.detail.timeProgram));
console.log("<<< Machine ended...");
// If you want to say that the clothes are dirty:
// return false
});
});
<button id="button">Wash my clothes</button>
编辑2
使用Promise更好地处理错误:
var button = document.getElementById('button');
button.addEventListener('click', async event => {
console.log("Putting the clothes in the washing machine.");
var listOfActions = [];
let cancelled = !button.dispatchEvent(new CustomEvent('startmachine', { 'detail': {timeProgram: 3000, listOfActions: listOfActions} }));
results = await Promise.all(listOfActions);
// Do not use == true or boolean to ensure returning nothing does not abort.
cancelled = cancelled || !results.every(x => x != false)
if (cancelled) {
console.log("Picking the dirty clothes.");
} else {
console.log("Picking the washed clothes.");
}
});
button.addEventListener('startmachine', event => {
event.detail.listOfActions.push((async () => {
console.log(">>> Machine started...");
await new Promise(r => setTimeout(r, event.detail.timeProgram));
console.log("<<< Machine ended...");
// If you want to say that the clothes are dirty:
//return false
})());
// ^-- The () is useful to push a promise and not an async function.
// I could also have written let f = async () => { ... }; event....push(f())
});
<button id="button">Wash my clothes</button>