javascript - 从 setTimeout 调用生成器函数
问题描述
以下 js 代码在 firefox、chrome 和 nodejs 的开发者控制台中也失败。无法弄清楚为什么?
function* x() {}
let y = x()
setTimeout(y.next, 100)
火狐中的错误
TypeError:在不兼容的窗口上调用的 CallGeneratorMethodIfWrapped 方法
铬错误
Uncaught TypeError: Method [Generator].prototype.next 在不兼容的接收器上调用 # 在 next()
node.js 中的错误
timers.js:475
timer._onTimeout();
^
TypeError: Method [Generator].prototype.next called on incompatible receiver #<Timeout>
at Timeout.next [as _onTimeout] (<anonymous>)
at ontimeout (timers.js:475:11)
at tryOnTimeout (timers.js:310:5)
at Timer.listOnTimeout (timers.js:270:5)
解决方案
当您作为要调用的函数传递时,该对象y
将丢失。y.next
你可以这样做:
setTimeout(y.next.bind(y), 100)
当您传递y.next
时,它会到达y
对象并获取对next
函数的引用,并且它仅传递对next
函数的引用。next
它是对与对象完全没有关联的函数的通用引用y
。然后,稍后当setTimeout()
触发时,它只是next
自己调用函数,并且y
在函数调用中不使用对象。这意味着在next
执行时,该this
值将是undefined
并且不会是适当的y
对象。
你可以想象它这样做:
let x = y.next;
setTimeout(x, 100);
y
与传递给无关setTimeout()
。它将将该next()
方法作为普通函数调用。如果你这样做,你可能会看到同样的问题:
let x = y.next;
x();
根据它的设计,setTimeout()
只调用函数,如fn()
. 它不像y.next()
. 要调用方法,必须在实际函数调用中使用对象引用,如y.next()
. setTimeout()
不这样做。它只是调用函数。
因此,.bind()
创建一个小的存根函数,然后它将为您正确调用它。因此,如上所示使用它与此类似:
let x = function() {
y.next();
}
setTimeout(x, 100);
或者,内联版本:
setTimeout(function() {
y.next();
}, 100);
推荐阅读
- mongodb - 解析 stateful.yaml 时出错:将 YAML 转换为 JSON 时出错:yaml:第 35 行:此上下文中不允许映射值
- arrays - 多个矩阵子集并存储在数组中
- c# - 将 SqlParameter 添加到 SqlCommand 的通用方法
- php - 如何在 PHP 中同步来自两个不同 RDMBS(SQL Server 和 MySQL)的两个相同表之间的差异
- c++ - c++中的内联函数实际上在编译的哪个阶段进行扩展?
- raku - 数组上的 perl6 文本替换
- javascript - 如何使用地图将道具从父母传递给孩子
- arrays - 如何在 3D numpy 数组中删除有条件的元素行?
- python - 如何匹配异构的空白字符序列?
- css - 背景响应的问题