- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) > web開(kāi)發(fā) >
- D3.js中強制異步文件如何讀取同步
這篇文章主要為大家展示了“D3.js中強制異步文件如何讀取同步”,內容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習一下“D3.js中強制異步文件如何讀取同步”這篇文章吧。
發(fā)現問(wèn)題
在使用d3.js時(shí),我們經(jīng)常會(huì )使用d3.csv()
或者d3.json()
函數來(lái)從文件中讀取出數據,不幸的是,偶爾代碼的結果并不是我們預料的那樣。習慣了過(guò)程式編程的我開(kāi)始的時(shí)候也是這樣,最讓人頭疼的是javascript并不會(huì )告訴你問(wèn)題出在哪里了。我第一次遇到這個(gè)問(wèn)題的時(shí)候,找了半天bug,確定代碼主體部分沒(méi)有問(wèn)題之后,我只能開(kāi)始使用console.log()
將變量一個(gè)一個(gè)的輸出到控制臺里。
第一次遇到這個(gè)問(wèn)題時(shí)的圖片是這樣的:
問(wèn)題出在第72行和第75行,中間幾行完全沒(méi)有對ordertxt進(jìn)行操作,但是最后的結果就是和預想的輸出不吻合,后來(lái)找了個(gè)其他方法把這個(gè)問(wèn)題給解決了,今天又遇到了類(lèi)似的這個(gè)問(wèn)題,就下決心來(lái)拔掉這根刺。
試驗
\<script\> console.log("before csv1 "); d3.csv("flowers.csv", function(data) {console.log(data)}); console.log("before csv2"); d3.csv("flowers.csv",function(error,data2) {console.log(error, data2)}); \</script\>
believe it or not,上面的代碼將產(chǎn)生下面圖中的輸出結果,因為javascript的 異步特性 。說(shuō)到異步,大部分時(shí)候是讓人開(kāi)心的,但偶爾也會(huì )令人頭疼,至少在這里,就是令人頭疼。
解決方法1
第一次遇到這個(gè)問(wèn)題的時(shí)候,我巧妙的繞開(kāi)了這個(gè)問(wèn)題,使用的方法是:我把數據的處理放在了d3.csv(“flowers.csv”,function(data){dealWithData()…})
回調函數里面,這樣數據的處理就和d3的讀文件操作變成了綁在一根繩上的螞蚱了,要么一起執行完,要么都不執行。貌似世界和平了,但是今天下午又遇到了這個(gè)問(wèn)題,而且數據的變化是隨時(shí)隨地的,可不是和上一次遇到的那樣,所有會(huì )發(fā)生的變化都可以預先寫(xiě)成代碼的。于是我開(kāi)始了對解決方法的苦苦追尋。
解決方法2
第二種方法是借助一些helper類(lèi)庫(queue.js)來(lái)強制數據在加載完成之后才去觸發(fā)相應的操作。這種方法是我在網(wǎng)上看到的,并沒(méi)有去親自試過(guò),也許會(huì )成功,但是對于我們會(huì )變化的數據,不能提前將處理邏輯寫(xiě)出代碼,這種方法還是不合格的。
解決方法3
第三種方法是在stack overflow里查到的,試了一下是可以的,他這里用的是d3.text()函數,將文件先load進(jìn)來(lái),然后再使用d3.csv.parse
或者d3.csv.parseRows
,這樣就會(huì )是同步的了。參考文末的Reference 3的實(shí)現。
解決方法4
方法4是我自己想出來(lái)的,最近幾天一直在做angular和d3結合在一起的工作,我就在想能否借助angular來(lái)幫助我們完成呢?萬(wàn)幸,Angular中確實(shí)有這么一個(gè)函數,似乎就是為這個(gè)問(wèn)題量身定做的,且解決了前面的方法都沒(méi)有解決的數據后期動(dòng)態(tài)變化的問(wèn)題。這個(gè)函數就是 $watch
函數。
$watch列表
每當我們在視圖中追蹤一個(gè)事件時(shí),會(huì )給它注冊一個(gè)回調函數,然后希望在頁(yè)面中觸發(fā)該事件時(shí)調用這個(gè)回調函數。比如AngularJS中最令人印象深刻的雙向綁定,在input中輸入一個(gè)字母,有著(zhù)相同ng-model的變量就會(huì )跟著(zhù)input的輸入而發(fā)生改變。
發(fā)生這一變化的原因是我們把UI中的輸入字段綁定給了$scope.name
屬性,為了更新這個(gè)視圖,Angular需要 追蹤變化 ,是通過(guò)給$watch
列表添加一個(gè)監控函數做到這一點(diǎn)的。
臟檢查
臟檢查是一個(gè)簡(jiǎn)單的過(guò)程,可歸結為一個(gè)非?;A的概念:檢查值是否發(fā)生了變化,而整個(gè)應用還沒(méi)同步該變化。Angular會(huì )遍歷$watch
列表,只要有任何的值發(fā)生比變化,應用將會(huì )退回到$watch
循環(huán)中,直到檢測到不在發(fā)生任何變化。
$watch
$scope
對象上的$watch
方法會(huì )給Angular事件循環(huán)內的每個(gè)$digest調用裝配一個(gè)臟檢查,如果在檢測到變化,Angular總是會(huì )返回$digest
循環(huán)。
$watch
函數本身接受兩個(gè)必要參數和一個(gè)可選的參數,第一個(gè)參數是watch的對象,第二個(gè)參數是 回調函數 ,一旦watch的對象變了的時(shí)候觸發(fā);可選的參數是一個(gè)bool值,告訴Angular是否檢查 嚴格相等 。
關(guān)于回調函數和嚴格相等,還有一些想說(shuō)的。
回調函數
我一直是這么理解回調函數的,研究生的導師會(huì )分配給每個(gè)研究生活去干,而他自己也有自己的事情,如果給某個(gè)研究生安排的活他做好了,就過(guò)來(lái)給他說(shuō)一聲,導師負責匯總,將活寫(xiě)成論文發(fā)表出去。這其實(shí)就是回調函數工作的原理。當然導師不可能在這邊等著(zhù)研究生干活,自己什么都不干;或者自己什么都干了,也沒(méi)研究生什么事了。
嚴格相等
比如有一個(gè)數組,a=【1,2,3】,后面修改了a【0】=2,在A(yíng)ngularJS看來(lái),這個(gè)數組并沒(méi)有發(fā)生變化,因為還是3個(gè)變量,而如果從嚴格意義上來(lái)說(shuō),它已經(jīng)發(fā)生了變化,這就是嚴格相等和相等的不同,在javascript中,也有==和===的區別。
實(shí)現
寫(xiě)到這里,大家應該知道該怎么做了,即調用$watch
函數來(lái)觀(guān)測我們需要關(guān)注的data,每當發(fā)生變化的時(shí)候,就根據新的data,重新繪制圖標。因此,我們最好將render的過(guò)程抽象成一個(gè)函數,方便我們后期調用。比如,我們想要觀(guān)測data數組的變化,并且根據它的變化來(lái)重新繪制圖片。那么我們的代碼實(shí)現就應該像下面這樣。
scope.$watch("data", function() { render(); //render函數是繪制的過(guò)程,換成自己的即可。 },true);
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系站長(cháng)郵箱:ts@56dr.com進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。
Copyright ? 2009-2021 56dr.com. All Rights Reserved. 特網(wǎng)科技 版權所有 珠海市特網(wǎng)科技有限公司 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2 建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站