【发布时间】:2018-05-27 06:08:28
【问题描述】:
我正在尝试构建一种方法来创建可以产生 DOM 事件的生成器。更一般地说,我想创建一种将事件系统转换为产生事件的异步系统的方法。
我的初始代码示例有效,但我可以看到从 Promise 中解除 resolve 函数的问题,以便在事件进入时调用该函数。
class EventPropagation {
constructor(id) {
const button = document.getElementById(id);
let _resolve;
button.addEventListener("click", event => {
if (_resolve) {
_resolve(event);
}
});
let _listen = () => {
return new Promise(resolve => {
_resolve = resolve;
});
}
this.subscribe = async function*() {
const result = await _listen();
yield result;
yield * this.subscribe();
}
}
}
async function example() {
const eventPropagation = new EventPropagation("btn");
for await (const event of eventPropagation.subscribe()) {
console.log(event);
}
}
// call the example function
example();
我的问题是:有没有更好的方法来构建这样的东西?有很多事情需要考虑,比如同时出现多个事件或清理侦听器和订阅。我的目标不是最终得到一个响应式库,但我确实想创建小的透明函数来异步产生事件。
2017 年 12 月 14 日编辑(根据 Bergi 的评论编辑)
异步生成器
Babel 和后来的一些插件;异步生成器不是问题:
const throttle = ms => new Promise(resolve => setTimeout(resolve, ms));
const getData = async() => {
const randomValue = Math.floor(Math.random() * 5000 + 1);
await throttle(randomValue);
return `The random value was: ${randomValue}`;
}
async function* asyncRandomMessage() {
const message = await getData();
yield message;
// recursive call
yield *asyncRandomMessage();
}
async function example() {
for await (const message of asyncRandomMessage()) {
console.log(message);
}
}
// call it at your own risk, it does not stop
// example();
我想知道的是如何将一系列单独的回调调用转换为异步流。我无法想象这个问题没有得到解决。当我查看在 cmets 中显示的 Bergi 库时,我看到了与我所做的相同的实现,即:“将解析和拒绝函数存储在事件处理程序可以调用它们的地方。”我无法想象这将是解决这个问题的正确方法。
【问题讨论】:
-
看起来您正在尝试实现异步生成器。这些还不存在,但是如果您查看提案,您还会发现this issue 甚至library doing all the work for you。另请注意,Observables 可能更适合表示 DOM 事件。
-
感谢您的评论和链接。我想将此模式用于每种类型的异步流:DOM 事件、Firebase、WebWorkers 等。我正在为所有这些异步序列寻找一种易于实现的解决方案。如果我不能像这样构建它,我会定义。使用观察者模式。