偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

在 Ember 中處理異步

開發(fā) 前端
許多 Ember 的概念,比如綁定和計(jì)算屬性,其設(shè)計(jì)是為了完成異步行為的處理。

許多 Ember 的概念,比如綁定和計(jì)算屬性,其設(shè)計(jì)是為了完成異步行為的處理。

沒有 Ember 的情況

我們首先來看一看用 jQuery 或基于事件的 MVC 框架如何管理異步行為。

讓我們使用一個(gè) web 應(yīng)用中最常見的異步行為——發(fā)起一個(gè) Ajax 請求——來作為例子。 瀏覽器發(fā)起 Ajax 請求的 API 提供了一個(gè)異步的 API。jQuery 包裝器也可以實(shí)現(xiàn):

  1. jQuery.getJSON('/posts/1'function(post) { 
  2.   $("#post").html("<h1>" + post.title + "</h1>" + 
  3.     "<div>" + post.body + "</div>"); 
  4. }); 

在純 jQuery 應(yīng)用中,你會用這個(gè)回調(diào)來隨意進(jìn)行要更改到 DOM 的更改。

當(dāng)使用一個(gè)基于事件的 MVC 框架,會把邏輯從回調(diào)中拿出而放進(jìn)模型和視圖對象里。 這改進(jìn)了很多東西,但仍未擺脫顯式處理異步回調(diào)的需求:

  1. Post = Model.extend({ 
  2.   author: function() { 
  3.     return [this.salutation, this.name].join(' '
  4.   }, 
  5.   toJSON: function() { 
  6.     var json = Model.prototype.toJSON.call(this); 
  7.     json.author = this.author(); 
  8.     return json; 
  9.   } 
  10. }); 
  11. PostView = View.extend({ 
  12.   init: function(model) { 
  13.     model.bind('change'this.render, this); 
  14.   }, 
  15.   template: _.template("<h1><%= title %></h1><h2><%= author %></h2><div><%= body %></div>"), 
  16.   render: function() { 
  17.     jQuery(this.element).html(this.template(this.model.toJSON()); 
  18.     return this
  19.   } 
  20. }); 
  21. var post = Post.create(); 
  22. var postView = PostView.create({ model: post }); 
  23. jQuery('#posts').append(postView.render().el); 
  24. jQuery.getJSON('/posts/1'function(json) { 
  25.   // set all of the JSON properties on the model 
  26.   post.set(json); 
  27. }); 

這個(gè)例子沒有用任何特殊的 JavaScript 庫,但它的實(shí)現(xiàn)途徑是事件驅(qū)動(dòng)的 MVC 框架 中的典型。它實(shí)現(xiàn)了異步事件的組織,但異步行為仍然在核心程序模型中。

Ember 的方法

總體而言,Ember 的目的是消除顯式形式的異步行為。如我們之后會見到的,這給予了 Ember 合并多個(gè)具有相同結(jié)果事件的能力。

它也提供了高層抽象,消滅手動(dòng)注冊/反注冊事件監(jiān)聽器來執(zhí)行大多數(shù)任務(wù)的需求。

你一般會為這個(gè)例子使用用 ember-data ,當(dāng)讓我們看看如何用 jQuery 來為 Ember 中的 Ajax 模型化上面的例子。

  1. App.Post = Ember.Object.extend({ 
  2. }); 
  3. App.PostController = Ember.ObjectController.extend({ 
  4.   author: function() { 
  5.     return [this.get('salutation'), this.get('name')].join(' '); 
  6.   }.property('salutation''name'
  7. }); 
  8. App.PostView = Ember.View.extend({ 
  9.   // the controller is the initial context for the template 
  10.   controller: null
  11.   template: Ember.Handlebars.compile("<h1>{{title}}</h1><h2>{{author}}</h2><div>{{body}}</div>"
  12. }); 
  13. var post = App.Post.create(); 
  14. var postController = App.PostController.create({ content: post }); 
  15. App.PostView.create({ controller: postController }).appendTo('body'); 
  16. jQuery.getJSON("/posts/1"function(json) { 
  17.   post.setProperties(json); 
  18. }); 

與上面的例子相反,Ember 的實(shí)現(xiàn)方法消滅了當(dāng) post 的屬性變更時(shí)顯式注冊觀察者 的需求。

{{title}} 、 {{author}} 和 {{body}} 模板元素被限定到 PostController 上的那些元素中。當(dāng) PostController 的內(nèi)容更改,它自動(dòng)傳播那些變更到 DOM。

為 author 使用一個(gè)計(jì)算屬性消滅了在底層屬性變更時(shí)顯式地調(diào)用回調(diào)中計(jì)算的需 求。

除此之外,Ember 的綁定系統(tǒng)自動(dòng)跟蹤從 getJSON 回調(diào)中設(shè)置的 salutation 和 name 到 PostController 中的計(jì)算屬性,并且始終把變化傳播到 DOM 中。

益處

因?yàn)?Ember 經(jīng)常負(fù)責(zé)傳播變更,它可以保證在響應(yīng)每個(gè)用戶事件上一個(gè)變更只傳播一 次。

讓我們再看一看 author 計(jì)算屬性。

  1. App.PostController = Ember.ObjectController.extend({ 
  2.   author: function() { 
  3.     return [this.get('salutation'), this.get('name')].join(' '); 
  4.   }.property('salutation''name'
  5. }); 

因?yàn)槲覀円呀?jīng)指定了它依賴于 salutation 和 name ,這兩個(gè)依賴的任何一個(gè)的變 更都會使屬性無效,這會觸發(fā)對 DOM 中 {{author}} 的更新。

想象在響應(yīng)一個(gè)用戶事件時(shí),我要做這些事:

  1. post.set('salutation'"Mrs."); 
  2. post.set('name'"Katz"); 

你會臆斷這些變更會導(dǎo)致計(jì)算屬性被無效兩次,導(dǎo)致更新 DOM 兩次。而事實(shí)上,這在 使用事件驅(qū)動(dòng)的框架上確實(shí)會發(fā)生。

在 Ember 中,計(jì)算屬性會只重新計(jì)算一次,并且 DOM 也只會更新一次。

這是如何實(shí)現(xiàn)的呢?

當(dāng)你對 Ember 中的一個(gè)屬性做出更改,它不會立即傳播變更。除此之外,它立即無效 任何有依賴的屬性,但把實(shí)際的修改放入隊(duì)列來讓它在之后發(fā)生。

對 salutation 和 name 屬性都修改會無效 author 屬性兩次,但隊(duì)列會智能地 合并那些變更。

一旦所有當(dāng)前用戶事件的事件處理器完成,Ember 刷新隊(duì)列,把變更向下傳播。在這種 情況下,這意味著被無效的 author 屬性會無效 DOM 中的 {{author}} ,這會讓 單次請求只重新計(jì)算信息并更新自己一次。

這個(gè)機(jī)制是 Ember 的根基。 在 Ember 中,應(yīng)該總是假定一個(gè)你所做變更的副作 用會在之后發(fā)生。通過做這個(gè)假設(shè),你允許 Ember 來合并單次調(diào)用中相同的副作用。

總而言之,事件驅(qū)動(dòng)系統(tǒng)的目標(biāo)是從監(jiān)聽器產(chǎn)生的負(fù)效用中解耦數(shù)據(jù)操作,所以你不應(yīng) 該假定同步的副作用,即使在一個(gè)更關(guān)注事件的系統(tǒng)中。事實(shí)上,在 Ember 中副作用 不會立刻傳播,消除了欺騙并偶然地把應(yīng)該分開的代碼耦合在一起的誘因。

副作用回調(diào)

既然你不能依賴同步的副作用,你會好奇如何確保特定的行為在恰好的時(shí)間發(fā)生。

例如,想象你有一個(gè)包含一個(gè)按鈕的視圖,并且你想用 jQuery UI 來樣式化這個(gè)按 鈕。因?yàn)橐晥D的 append 方法,如同 Ember 中的其它東西,推遲了它的副作用,怎 樣在正確的時(shí)間執(zhí)行 jQuery UI 代碼?

答案是生命周期回調(diào)。

  1. App.Button = Ember.View.extend({ 
  2.   tagName: 'button'
  3.   template: Ember.Handlebars.compile("{{view.title}}"), 
  4.   didInsertElement: function() { 
  5.     this.$().button(); 
  6.   } 
  7. }); 
  8. var button = App.Button.create({ 
  9.   title: "Hi jQuery UI!" 
  10. }).appendTo('#something'); 

這種情況下,一旦按鈕真正出現(xiàn)在 DOM 中,Ember 會觸發(fā) didInsertElement 回 調(diào),然后你可以做任何你想要做的工作。

生命周期回調(diào)方法有很多好處,即使我們并不需要擔(dān)憂延遲的插入。

首先,依賴同步的插入意味著 appendTo 的調(diào)用者要來觸發(fā)任何需要在附加元素后立 即運(yùn)行的行為。當(dāng)你的應(yīng)用變大后,你會發(fā)現(xiàn)在許多地方創(chuàng)建相同的視圖,并且需要擔(dān) 心它對每個(gè)地方的聯(lián)系。

生命周期回調(diào)消滅了實(shí)例化視圖和它的提交插入行為兩部分代碼的耦合。一般地,我們 發(fā)現(xiàn)不依賴于同步副作用導(dǎo)致了整體上的優(yōu)良設(shè)計(jì)。

第二,因?yàn)殛P(guān)于視圖生命周期的一切都在視圖本身內(nèi)部,按需重渲染 DOM 的部分對 Ember 是非常容易的。

例如,如果這個(gè)按鈕在一個(gè) {{#if}} 塊中,并且 Ember 需要從主分支切換到 else 節(jié),Ember 可以輕易實(shí)例化視圖并調(diào)用生命周期回調(diào)。

因?yàn)?Ember 強(qiáng)迫你定義一個(gè)完整定義的視圖,它可以控制在合適的場合創(chuàng)建并插入視 圖。

這也意味著所有的與 DOM 相關(guān)的代碼只在應(yīng)用中封裝好的幾個(gè)部分,所以 Ember 在 這些在回調(diào)之外的渲染過程中的部分有更多的自由。

觀察者

在一些罕見的情況,你會想要在屬性變更已經(jīng)傳播之后執(zhí)行特定的行為。正如前面一節(jié) 中所述,Ember 提供了一個(gè)機(jī)制來掛鉤到屬性變更通知。

讓我們返回“稱呼”的例子。

  1. App.PostController = Ember.ObjectController.extend({ 
  2.   author: function() { 
  3.     return [this.get('salutation'), this.get('name')].join(' '); 
  4.   }.property('salutation''name'
  5. }); 

如果我們想在作者變更時(shí)被通知,我們可以注冊一個(gè)觀察者。讓我們表示為視圖函數(shù) 想要被通知:

  1. App.PostView = Ember.View.extend({ 
  2.   controller: null
  3.   template: Ember.Handlebars.compile("<h1>{{title}}</h1><h2>{{author}}</h2><div>{{body}}</div>"), 
  4.   authorDidChange: function() { 
  5.     alert("New author name: " + this.getPath('controller.author')); 
  6.   }.observes('controller.author'
  7. }); 

Ember 在它成功傳播變更后觸發(fā)觀察者。在本例中,這意味著 Ember 會只對每個(gè)用戶 事件調(diào)用一次 authorDidChange ,即使 salutation 和 name 都有變更。

這為你提供了在屬性變更后執(zhí)行代碼的便利,而不強(qiáng)制所有的屬性變更同步。這基本上 意味著如果你需要對一個(gè)計(jì)算屬性的變更做一些手動(dòng)工作,你會得到相同的合并便利, 如同在 Ember 的綁定系統(tǒng)中一樣。

最后,你也可以手動(dòng)注冊觀察者,在對象定義之外:

  1. App.PostView = Ember.View.extend({ 
  2.   controller: null
  3.   template: Ember.Handlebars.compile("<h1>{{title}}</h1><h2>{{author}}</h2><div>{{body}}</div>"), 
  4.   didInsertElement: function() { 
  5.     this.addObserver('controller.name'function() { 
  6.       alert("New author name: " + this.getPath('controller.author')); 
  7.     }); 
  8.   } 
  9. }); 

盡管如此,當(dāng)你使用對象定義語法,Ember 會自動(dòng)在對象銷毀時(shí)銷毀觀察期。例如,一 個(gè) {{#if}} 語句從真值變?yōu)榧僦担珽mber 銷毀塊內(nèi)定義的所有試圖。作為這個(gè)過程 的一部分,Ember 也會斷開所有綁定和內(nèi)聯(lián)觀察者。

如果你手動(dòng)定義了一個(gè)觀察者,你需要確保移除了它。一般地,你會想要在與創(chuàng)建時(shí)相 反的回調(diào)中移除觀察者。在本例中,你會想要移除 willDestroyElement 的回調(diào)。

  1. App.PostView = Ember.View.extend({ 
  2.   controller: null
  3.   template: Ember.Handlebars.compile("<h1>{{title}}</h1><h2>{{author}}</h2><div>{{body}}</div>"), 
  4.   didInsertElement: function() { 
  5.     this.addObserver('controller.name'function() { 
  6.       alert("New author name: " + this.getPath('controller.author')); 
  7.     }); 
  8.   }, 
  9.   willDestroyElement: function() { 
  10.     this.removeObserver('controller.name'); 
  11.   } 
  12. }); 

如果你在 init 方法中添加了觀察者,你會想要在 willDestroy 回調(diào)中銷毀它。

總而言之,你會極少用這種方法注冊一個(gè)手動(dòng)的觀察者。為了保障內(nèi)存管理,我們強(qiáng)烈 建議盡可能把觀察者定義為對象定義的一部分。

原文鏈接:http://emberjs.torriacg.org/guides/asynchrony/

責(zé)任編輯:陳四芳 來源: emberjs.torriacg.org
相關(guān)推薦

2013-12-25 09:53:22

Ember.js應(yīng)用

2017-08-28 15:21:29

異步處理回調(diào)函數(shù)異步編程

2013-12-24 11:11:27

ember.jsJavascript

2013-12-24 15:56:20

2023-05-04 07:43:47

MySQL數(shù)據(jù)庫

2009-08-21 10:43:19

FlyTcpFrame

2009-07-07 09:41:02

異步ServletAJAX

2013-12-24 16:03:26

Ember.js視圖

2013-12-24 13:20:28

EmberEmber.js

2020-03-29 08:27:05

Promise異步編程前端

2010-12-01 14:34:59

AsyncTask異步處理任務(wù)Android

2015-03-09 09:44:35

GmailiOS

2023-10-28 16:30:19

Golang開發(fā)

2024-01-07 16:46:19

FiberHTTPWeb

2014-07-22 09:01:53

SwiftJSON

2022-04-29 07:35:49

SpringMVC構(gòu)造函數(shù)

2022-01-08 19:00:09

NumPyPython編程語言

2013-05-30 15:16:26

javaScriptMVC模式

2023-11-06 08:01:09

Go同步異步

2020-04-07 00:10:16

javascrip語言異步
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號