Javascript闭包:直接访问模型和使用变量之间的区别

时间:2016-09-11 17:46:06

标签: javascript

我注意到这段代码无法正常工作。

消息RENDER_IMAGE在有效负载中使用不同的图像多次广播,但下面代码中的self.model.get(“image”)始终返回最后一个图像。为什么?

bus.subscribe("RENDER_IMAGE", (message, payload) => {
    const self = this;
    self.model.set(payload);

    self.render().then(function() {
            bus.broadcast("IMAGE_RENDER_COMPLETE", self.model.get("image"));
        });
});

同时此代码的工作正确:

bus.subscribe("RENDER_IMAGE", (message, payload) => {
        const self = this;
        self.model.set(payload);
        const image = self.model.get("image"));

        self.render().then(function() {
                bus.broadcast("IMAGE_RENDER_COMPLETE", image;
            });
    });

1 个答案:

答案 0 :(得分:1)

在第一个示例中,您将在渲染完成后从模型中检索image字段。
与此同时,在第一次渲染完成之前,可能会触发一个或多个RENDER_IMAGE事件。每当此类事件触发时,您都在更新image字段。

即。发生类似这样的事情

RENDER_IMAGE triggered
Set image field            (image = 0)
Start render (0)

RENDER_IMAGE triggered
Set image field            (image = 1)
Start render (1)

Render finished (0)
Get image field (1, because image = 1)

Render finished (1)
Get image field (1, because image = 1)

在第二个示例中,您在设置后立即检索image。由于JavaScript是单线程的,因此在self.model.set(payload);执行之前不可能调用另一个const image = self.model.get("image"));

RENDER_IMAGE triggered
Set image field            (image = 0)
Get image field (0, because image = 0)
Start render (0)

RENDER_IMAGE triggered
Set image field            (image = 1)
Get image field (1, because image = 1)
Start render (1)

Render finished (0)

Render finished (1)

如果您仍然想知道为什么直接访问模型和使用变量之间存在差异:事件处理程序的每次调用都有自己的 image变量,但他们都访问相同的共享模型。

这是共享数据的特征之一,这就是为什么在处理异步流程时必须小心处理共享数据的原因。