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自定义功能函数实现动态添加网址参数修改网址参数值
Aug 02 Javascript
javascript实现阻止iOS APP中的链接打开Safari浏览器
Jun 12 Javascript
jQuery实现数秒后自动提交form的方法
Mar 05 Javascript
JS验证IP,子网掩码,网关和MAC的方法
Jul 02 Javascript
浅谈js中同名函数和同名变量的执行问题
Feb 12 Javascript
AngularJS改变元素显示状态
Apr 20 Javascript
原生JS发送异步数据请求
Jun 08 Javascript
Vue组件中prop属性使用说明实例代码详解
May 31 Javascript
Vue.js 利用v-for中的index值实现隔行变色
Aug 01 Javascript
js prototype和__proto__的关系是什么
Aug 23 Javascript
layui使用label标签的方法
Sep 14 Javascript
js实现炫酷光感效果
Sep 05 Javascript
浅谈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连接MySQL代码的参数说明
2008/06/07 PHP
PHP安装GeoIP扩展根据IP获取地理位置及计算距离的方法
2016/07/01 PHP
关于php中的json_encode()和json_decode()函数的一些说明
2016/11/20 PHP
php 数据结构之链表队列
2017/10/17 PHP
PHP用函数嵌入网站访问量计数器
2017/10/27 PHP
鼠标移动到一张图片时变为另一张图片
2006/12/05 Javascript
对setInterval在火狐和chrome切换标签产生奇怪的效果之探索,与解决方案!
2011/10/29 Javascript
js 完美图片新闻轮转效果,腾讯大粤网首页图片轮转改造而来
2011/11/21 Javascript
教你如何自定义百度分享插件以及bshare分享插件的分享按钮
2014/06/20 Javascript
JavaScript中的原型链prototype介绍
2014/12/30 Javascript
调试JavaScript中正则表达式中遇到的问题
2015/01/27 Javascript
js字符串操作方法实例分析
2015/05/06 Javascript
js实现为a标签添加事件的方法(使用闭包循环)
2016/08/02 Javascript
深入了解JavaScript的逻辑运算符(与、或)
2016/12/20 Javascript
JavaScript 程序错误Cannot use 'in' operator to search的解决方法
2017/07/10 Javascript
利用百度地图API获取当前位置信息的实例
2017/11/06 Javascript
浅谈Vue.use的使用
2018/08/29 Javascript
Intellij IDEA搭建vue-cli项目的方法步骤
2018/10/20 Javascript
微信小程序常用赋值方法小结
2019/04/30 Javascript
Vue实现商品详情页的评价列表功能
2019/09/04 Javascript
原生javascript单例模式的应用实例分析
2020/02/23 Javascript
koa中间件核心(koa-compose)源码解读分析
2020/06/15 Javascript
[00:31]2016完美“圣”典风云人物:国士无双宣传片
2016/12/04 DOTA
python使用pyqt写带界面工具的示例代码
2017/10/23 Python
Python实现计算圆周率π的值到任意位的方法示例
2018/05/08 Python
浅析python的优势和不足之处
2018/11/20 Python
Django中间件基础用法详解
2019/07/18 Python
django 文件上传功能的相关实例代码(简单易懂)
2020/01/22 Python
Pandas的Apply函数具体使用
2020/07/21 Python
python 利用百度API识别图片文字(多线程版)
2020/12/14 Python
史上最详细的Python打包成exe文件教程
2021/01/17 Python
Tory Burch英国官方网站:美国时尚生活品牌
2017/12/06 全球购物
自荐信怎么写好
2013/11/11 职场文书
物理分数没达标检讨书
2014/09/13 职场文书
2015年体育教学工作总结
2015/05/20 职场文书
详解vue身份认证管理和租户管理
2021/05/25 Vue.js