D3.js中强制异步文件读取同步的几种方法


Posted in Javascript onFebruary 06, 2017

发现问题

在使用d3.js时,我们经常会使用d3.csv()或者d3.json()函数来从文件中读取出数据,不幸的是,偶尔代码的结果并不是我们预料的那样。习惯了过程式编程的我开始的时候也是这样,最让人头疼的是javascript并不会告诉你问题出在哪里了。我第一次遇到这个问题的时候,找了半天bug,确定代码主体部分没有问题之后,我只能开始使用console.log()将变量一个一个的输出到控制台里。

第一次遇到这个问题时的图片是这样的:

D3.js中强制异步文件读取同步的几种方法

问题出在第72行和第75行,中间几行完全没有对ordertxt进行操作,但是最后的结果就是和预想的输出不吻合,后来找了个其他方法把这个问题给解决了,今天又遇到了类似的这个问题,就下决心来拔掉这根刺。

试验

\<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,上面的代码将产生下面图中的输出结果,因为javascript的 异步特性 。说到异步,大部分时候是让人开心的,但偶尔也会令人头疼,至少在这里,就是令人头疼。

D3.js中强制异步文件读取同步的几种方法

解决方法1

第一次遇到这个问题的时候,我巧妙的绕开了这个问题,使用的方法是:我把数据的处理放在了d3.csv(“flowers.csv”,function(data){dealWithData()…})回调函数里面,这样数据的处理就和d3的读文件操作变成了绑在一根绳上的蚂蚱了,要么一起执行完,要么都不执行。貌似世界和平了,但是今天下午又遇到了这个问题,而且数据的变化是随时随地的,可不是和上一次遇到的那样,所有会发生的变化都可以预先写成代码的。于是我开始了对解决方法的苦苦追寻。

解决方法2

第二种方法是借助一些helper类库(queue.js)来强制数据在加载完成之后才去触发相应的操作。这种方法是我在网上看到的,并没有去亲自试过,也许会成功,但是对于我们会变化的数据,不能提前将处理逻辑写出代码,这种方法还是不合格的。

解决方法3

第三种方法是在stack overflow里查到的,试了一下是可以的,他这里用的是d3.text()函数,将文件先load进来,然后再使用d3.csv.parse或者d3.csv.parseRows,这样就会是同步的了。参考文末的Reference 3的实现。

解决方法4

方法4是我自己想出来的,最近几天一直在做angular和d3结合在一起的工作,我就在想能否借助angular来帮助我们完成呢?万幸,Angular中确实有这么一个函数,似乎就是为这个问题量身定做的,且解决了前面的方法都没有解决的数据后期动态变化的问题。这个函数就是 $watch 函数。

$watch列表

每当我们在视图中追踪一个事件时,会给它注册一个回调函数,然后希望在页面中触发该事件时调用这个回调函数。比如AngularJS中最令人印象深刻的双向绑定,在input中输入一个字母,有着相同ng-model的变量就会跟着input的输入而发生改变。

发生这一变化的原因是我们把UI中的输入字段绑定给了$scope.name属性,为了更新这个视图,Angular需要 追踪变化 ,是通过给$watch列表添加一个监控函数做到这一点的。

脏检查

脏检查是一个简单的过程,可归结为一个非常基础的概念:检查值是否发生了变化,而整个应用还没同步该变化。Angular会遍历$watch列表,只要有任何的值发生比变化,应用将会退回到$watch循环中,直到检测到不在发生任何变化。

$watch

$scope对象上的$watch方法会给Angular事件循环内的每个$digest调用装配一个脏检查,如果在检测到变化,Angular总是会返回$digest循环。

$watch函数本身接受两个必要参数和一个可选的参数,第一个参数是watch的对象,第二个参数是 回调函数 ,一旦watch的对象变了的时候触发;可选的参数是一个bool值,告诉Angular是否检查 严格相等 。

关于回调函数和严格相等,还有一些想说的。

回调函数

我一直是这么理解回调函数的,研究生的导师会分配给每个研究生活去干,而他自己也有自己的事情,如果给某个研究生安排的活他做好了,就过来给他说一声,导师负责汇总,将活写成论文发表出去。这其实就是回调函数工作的原理。当然导师不可能在这边等着研究生干活,自己什么都不干;或者自己什么都干了,也没研究生什么事了。

严格相等

比如有一个数组,a=【1,2,3】,后面修改了a【0】=2,在AngularJS看来,这个数组并没有发生变化,因为还是3个变量,而如果从严格意义上来说,它已经发生了变化,这就是严格相等和相等的不同,在javascript中,也有==和===的区别。

实现

写到这里,大家应该知道该怎么做了,即调用$watch函数来观测我们需要关注的data,每当发生变化的时候,就根据新的data,重新绘制图标。因此,我们最好将render的过程抽象成一个函数,方便我们后期调用。比如,我们想要观测data数组的变化,并且根据它的变化来重新绘制图片。那么我们的代码实现就应该像下面这样。

scope.$watch("data", function() {
render();
//render函数是绘制的过程,换成自己的即可。
},true);

Reference

D3.js加载csv和json数据 http://www.bubuko.com/infodetail-942138.html

d3: make the d3.csv function syncronous http://stackoverflow.com/questions/19899005/d3-make-the-d3-csv-function-syncronous

read csv/tsv with no header line in D3 http://stackoverflow.com/questions/13870265/read-csv-tsv-with-no-header-line-in-d3
《AngularJS权威教程》 

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

Javascript 相关文章推荐
JS无限树状列表实现代码
Jan 11 Javascript
让你的博客飘雪花超出屏幕依然看得见
Jan 04 Javascript
WordPress中利用AJAX异步获取评论用户头像的方法
Jan 08 Javascript
浅谈Node.js:fs文件系统模块
Dec 08 Javascript
Web 开发中Ajax的Session 超时处理方法
Jan 19 Javascript
JS表格组件神器bootstrap table使用指南详解
Apr 12 Javascript
vue+vue-router转场动画的实例代码
Sep 01 Javascript
微信小程序如何获取手机验证码
Nov 04 Javascript
JavaScript继承与聚合实例详解
Jan 22 Javascript
微信小程序实现登录注册功能
Dec 29 Javascript
解决await在forEach中不起作用的问题
Feb 25 Javascript
vue css 相对路径导入问题级踩坑记录
Jun 05 Vue.js
浅谈Javascript事件对象
Feb 05 #Javascript
js中创建对象的几种方式
Feb 05 #Javascript
js实现增加数字显示的环形进度条效果
Feb 05 #Javascript
JS实现复制内容到剪贴板功能
Feb 05 #Javascript
js实现适合新闻类图片的轮播效果
Feb 05 #Javascript
BootStrap table删除指定行的注意事项(笔记整理)
Feb 05 #Javascript
JS前端开发判断是否是手机端并跳转操作(小结)
Feb 05 #Javascript
You might like
新手配置 PHP 调试环境(IIS+PHP+MYSQL)
2007/01/10 PHP
Discuz 5.0 中读取纯真IP数据库函数分析
2007/03/16 PHP
PHP连接SQLServer2005 的问题解决方法
2010/07/19 PHP
php中使用explode查找某个字符是否存在的方法
2011/07/12 PHP
在WordPress中使用PHP脚本来判断访客来自什么国家
2015/12/10 PHP
Smarty模板引擎缓存机制详解
2016/05/23 PHP
解决Laravel 使用insert插入数据,字段created_at为0000的问题
2019/10/11 PHP
alixixi runcode.asp的代码不错的应用
2007/08/08 Javascript
FormValid0.5版本发布,带ajax自定义验证例子
2007/08/17 Javascript
JavaScript 函数参数是传值(byVal)还是传址(byRef) 分享
2013/07/02 Javascript
jquery 添加节点的几种方法介绍
2013/09/04 Javascript
getAsDataURL在Firefox7.0下无法预览本地图片的解决方法
2013/11/15 Javascript
jQuery统计上传文件大小的方法
2015/01/24 Javascript
jquery实现左右滑动菜单效果代码
2015/08/27 Javascript
bootstrap3 兼容IE8浏览器!
2016/05/02 Javascript
JavaScript实现DOM对象选择器
2016/09/24 Javascript
Node.js实现文件上传的示例
2017/06/28 Javascript
详解mpvue小程序中怎么引入iconfont字体图标
2018/10/01 Javascript
bootstrap-treeview实现多级树形菜单 后台JSON格式如何组织?
2019/07/26 Javascript
Vue数组响应式操作及高阶函数使用代码详解
2020/08/01 Javascript
详解为什么Vue中的v-if和v-for不建议一起用
2021/01/13 Vue.js
在Python中用has_key()方法查找键是否存在的教程
2015/05/21 Python
Python读取图片为16进制表示简单代码
2018/01/19 Python
python实现从pdf文件中提取文本,并自动翻译的方法
2018/11/28 Python
PyQt5实现五子棋游戏(人机对弈)
2020/03/24 Python
Python加载数据的5种不同方式(收藏)
2020/11/13 Python
详解python使用金山词霸的翻译功能(调试工具断点的使用)
2021/01/07 Python
HTML5 实现图片上传预处理功能
2020/02/06 HTML / CSS
Agoda.com官方网站:便宜预订全球酒店,高达80%的折扣
2018/04/04 全球购物
财务管理专业应届毕业生求职信
2013/09/22 职场文书
《老王》教学反思
2014/02/23 职场文书
交通事故赔偿协议书
2014/04/15 职场文书
运动会演讲稿
2014/05/07 职场文书
党的群众路线教育实践活动学习计划
2014/11/03 职场文书
先进基层党组织事迹材料
2014/12/25 职场文书
小学生安全教育主题班会
2015/08/12 职场文书