2016-09-11 36 views
0

我注意到,這段代碼不能像我期望的那樣工作。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; 
      }); 
    }); 
+0

[JavaScript閉合內循環 - 簡單實用示例]的可能重複(http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – JJJ

+0

所以,你不能使用第二種方法呢? – Endless

+0

@Endless我需要像在第二種情況下的行爲。我是對的嗎?當我將圖像保存爲一個變量時 - 它會保留這個值,直到它將用於承諾?爲什麼模型不保留這個值? – francesca

回答

1

在第一個例子,你從模型檢索image後的渲染完成。
與此同時,一個或多個RENDER_IMAGE事件可能在第一個渲染完成之前被觸發。每次發生此類事件時,都會更新image字段。

I.e.這樣的事情發生

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是單線程的,不可能是之前執行const image = self.model.get("image"));另一個self.model.set(payload);被稱爲:

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變量,但他們都訪問相同,共享模型。

這是共享數據的特徵之一,這就是爲什麼共享數據在處理異步過程時必須謹慎處理的原因。

+0

非常感謝! – francesca

相關問題