【问题标题】:Why can't the generators next function be a callback function for an event listener [duplicate]为什么生成器的下一个函数不能成为事件侦听器的回调函数[重复]
【发布时间】:2015-10-21 23:21:57
【问题描述】:

我正在尝试使用生成器。当我尝试这段代码时,我遇到了意想不到的错误:

Uncaught TypeError: Method [Generator].prototype.next 在不兼容的接收器上调用# 或者 TypeError: 在不兼容的 HTMLButtonElement 上调用 CallStarGeneratorMethodIfWrapped 方法

我的问题,它不起作用吗?这些错误消息背后的含义是什么?最重要的是;为什么 first().next 不作为普通函数处理?为什么 addEventListener 关心 first().next 函数的起源。在控制台中键入 first().next。它说功能。下面注释了一个与下一个类似的函数,但它总是产生相同的结果。

您可以尝试重现的代码:

<html>
<button id="test">Click</button>
<script>

var first = function* (){
    console.log("first click");
    yield true;
    console.log("second click");
    yield true;
};

document.getElementById("test").addEventListener('click', first().next);

/*var wouldwork = function (){
    console.log("would work");
    return { value: true, done: false };
    // same as the next returns
};*/
/*document.getElementById("test").addEventListener('click', wouldwork);*/
</script>
</html>

另一种选择是将带有正确上下文的 next 放在另一个函数中。为此,我们将迭代器存储在一个变量中。

var iterator = first();

document.getElementById("test").addEventListener('click',

    function (event){return iterator.next();}

    //context of next is always the correct one

);

如果这种情况更频繁地发生,最好创建一个名为 createNext 的新函数,它以更纯粹的函数风格返回下一个函数

var createNext = function (generatorFunction){

    var iterator = generatorFunction();

    return function() {

        return iterator.next();

    };

};



document.getElementById("test").addEventListener('click',

    createNext(first)

);

【问题讨论】:

  • 可能是因为this关键字在两个函数内部都有使用,但是在事件监听函数(按钮元素)和生成器的next函数(生成器本身,也许)。
  • () =&gt; first().next()
  • 确实与this 有关系,因为var f = first(); ...addEventListener('click', f.next.bind(f)); 有效。
  • @zerkms:你不想再打电话给first()

标签: javascript dom generator


【解决方案1】:

jsFiddle Demo

事件监听的工作方式是它将使用call 调用函数句柄,并将this 绑定从其执行上下文分配给被调用的函数句柄。所以this 将被绑定为next 被调用的上下文。这就是为什么它不像写的那样工作。

接下来,实际上是从生成器函数中获取函数以进行迭代的问题。 “调用生成器函数不会立即执行其主体;而是返回该函数的迭代器对象。”。这意味着是的,first().next 一个函数对象,但它不是您要传递的句柄。您只是想使用迭代器函数本身,但那将是first(),那么如果您希望它每次都调用下一次,它是如何工作的呢?

这里的一个选项是简单地获取您的生成器函数并稍后将迭代器函数作为绑定传递。为了在.next 中维护迭代器函数的绑定,您可以这样做:

document.getElementById("test").addEventListener('click', first().next.bind(first()));

这会将first() 的迭代器函数绑定到迭代器函数的.next 函数。有点乱。对 first() 的第一次调用公开了迭代器函数,然后访问它的下一个函数,第二次调用只是将下一个函数的 this 绑定到迭代器函数,否则当 eventListener 使用 call 覆盖 this 绑定时,迭代器函数将被覆盖.

您可以在此处阅读有关这些生成器函数及其迭代器的更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*

【讨论】:

  • 如何使用 addEventListener 在 saga 中进行 put 操作?当我使用函数调用进行操作时(yield someFunc())但是当我写yield put(action()) 时不是(
猜你喜欢
  • 2015-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-31
  • 2023-02-18
  • 1970-01-01
  • 2020-04-06
相关资源
最近更新 更多