我有以下代码:
let bindings =
{
on : (messageName,callback) =>
{
bindings[messageName] = callback
}
}
bindings.on('test',(params) =>
{
setTimeout( () =>
{
console.log("call id " , params.callId)
},~~(Math.random()*100))
})
let data = {callId : 1 }
for (let i=0;i<5;i++)
{
bindings['test'](data)
data.callId++
}
它产生输出
call id 6
call id 6
call id 6
call id 6
call id 6
call id 6
我知道这个问题可以通过绑定https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Function/bind来解决,但我找不到正确的方法来实现它并保持实际设计
添加const修复问题,但我想找到一种更优雅/通用的方法来解决问题
bindings.on('test',(params) =>
{
const callId = params.callId
setTimeout( () =>
{
console.log("call id " , callId)
},~~(Math.random()*100))
})
答案 0 :(得分:0)
它不是关于事件逻辑的实现,而是使用由循环更新的引用来调用它。
由于内部setTimeout
实现是异步执行,因此调用循环在执行第一个事件逻辑之前完全执行。因此输入params
是对象data
的引用,当循环完成时,callId
值现在为6,当任何异步调用引用时,该值将为该值
基本上for
循环排队5个异步操作,其中每个操作都使用相同的引用对象data
。循环还为每次迭代更新data
对象的属性值。由于JavaScript处理异步操作的方式,循环将在任何异步操作开始之前完成,因为它仍然遵循脚本的初始同步执行。
解决此问题的一种方法是为每个循环迭代创建一个新的输入对象:
let bindings = {
on: (messageName, callback) => {
bindings[messageName] = callback
}
}
bindings.on('test', (params) => {
setTimeout(() => {
console.log("call id ", params.callId)
}, ~~(Math.random() * 100));
});
for (let i = 0; i < 5; i++) {
bindings['test']({callId: i + 1});
}
&#13;