原子操作这是Java多线程编程的老生常谈了。所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。

当然JS是单线程的,所以不存在线程打断这么一说,我只是从Java中借引了这么一个概念。如果一段JS代码在执行过程中没有未知操作被引入,那么这段代码就是100%可控和安全的,这就是原子操作。反之非原子操作可能会因为外界操作的引入导致代码变得难以控制而产生隐晦的bug。

下面举例说明非原子操作可能会带来的问题

function start()
{
player = new Player();
player.start();
fireEvent('start');
player.resume();
fireEvent('play');
} function stop()
{
player.pause();
fireEvent('pause');
player.stop();
player = null;
fireEvent('stop');
}

这段代码中定义两个方法,start表示开始播放视频,里面分别有两段原子操作,在每个原子操作结束之后都向外发送了事件;stop方法类似。代码看起来简单而完美,但由于这两个方法都不是原子操作,所以可能会存在隐患。

下面我们用同样简单的方式使用这两个方法就会产生混乱的结果。

on('start', function(){
stop();
});
start();

这段代码试图让播放器一开始播放就停止,意图明确。但是它却会让实际执行结果变成下面这样

player = new Player();
player.start();
fireEvent('start');
//监听start事件后引入的操作
player.pause();
fireEvent('pause');
player.stop();
player = null;
fireEvent('stop');
//end
player.resume();
fireEvent('play');

这段代码对外界来说居然在stop事件发生之后还会发生一次play事件,堪称诡异。

究其原因是因为触发play事件后引入外部操作导致下一个原子操作所依赖的前提改变。这就是我说的非原子操作的隐患。

那么如何避免这种问题呢,把代码改成这样就行

function start()
{ if (!started)
{
player = new Player();
player.start();
started = true;
fireEvent('start');
} if (started && !played)
{
player.resume();
played = true;
fireEvent('play');
}
} function stop()
{ if (started && played)
{
player.pause();
played = false;
fireEvent('pause');
} if (started)
{
player.stop();
player = null;
started = false;
fireEvent('stop');
}
}

只需要给每个原子操作加上足够的前提判断就可以避免上述问题。

有时候我们无法避免非原子操作,但是我们要认清哪些是原子操作,不要想当然得认为上一个原子操作产生的结果必然会是下一个原子操作的环境。在每个原子操作前加上足够的判断。

JS(AS)中的原子操作的更多相关文章

  1. Firebug中调试中的js脚本中中文内容显示为乱码

    Firebug中调试中的js脚本中中文内容显示为乱码 设置 页面 UFT-8 编码没用, 解决方法:点击 "Firebug"工具栏 中的"选项"---" ...

  2. js文件中函数前加分号和感叹号是什么意思?

    本文转自:http://blog.csdn.net/h_o_w_e/article/details/51388500 !function(){}();   !有什么用? 从语法上来开,JavaScri ...

  3. Angularjs在控制器(controller.js)的js代码中使用过滤器($filter)格式化日期/时间实例

    Angularjs内置的过滤器(filter)为我们的数据信息格式化提供了比较强大的功能,比如:格式化时间,日期.格式化数字精度.语言本地化.格式化货币等等.但这些过滤器一般都是在VIEW中使用的,比 ...

  4. 解决webkit浏览器中js方法中使用window.event提示未定义的问题

    这实际上是一个浏览器兼容性问题,根源百度中一大堆,简要说就是ie中event对象是全局变量,所以哪里都能使用到,但是webkit内核的浏览器中却不存在这个全局变量event,而是以一个隐式的局部变量的 ...

  5. 在JS方法中返回多个值的三种方法

    在使用JS编程中,有时需要在一个方法返回两个个或两个以上的数据,用下面的几种方法都可以实现: 1 使用数组的方式,如下: <html> <head> <title> ...

  6. 关于js代码中与或运算符||&&的妙用

    看bootstrap时看到如下一行JavaScript代码产生了疑惑. return window.pageYOffset || e.scrollTop ||在这里的作用是什么呢? 首先明确概念,在j ...

  7. Handlebars.js循环中索引(@index)使用技巧(访问父级索引)

    使用Handlebars.js过程中,难免会使用循环,比如构造数据表格.而使用循环,又经常会用到索引,也就是获取当前循环到第几次了,一般会以这个为序号显示在页面上. Handlebars.js中获取循 ...

  8. JS 正则表达式中的特殊字符

    正则表达式中的特殊字符 字符 含意 \ 做为转意,即通常在"\"后面的字符不按原来意义解释,如/b/匹配字符"b",当b前面加了反斜杆后/\b/,转意为匹配一个 ...

  9. js jquery中 的数据类型

    任何一门语言, buguan 是动态的, 还是像C语言的, 都有严格的 类型 "概念的", 这个是由于 编译器和解释器要求的, 需要的. 所以在是使用像 js, jquey ,ph ...

  10. 在Ext JS 6中添加本地化包

    我在官方论坛发的帖子终于有人恢复了,也终于知道如何添加本地化包了.在Ext JS 6中,Ext JS属于经典工具包,而本地化是包含在经典工具包中,因而在app.json中,要添加本地化包,必须在cla ...

随机推荐

  1. 剑指offer系列34----按之字形顺序打印二叉树

    [题目]请实现一个函数按照之字形打印二叉树, * 即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印, * 其他行以此类推. 未优化,不是最优解,博主用的是队列 ...

  2. php特殊字符过滤,html标签处理

    1,magic_quotes_gpc  默认情况下,PHP 指令 magic_quotes_gpc 为 on,对所有的 GET.POST 和 COOKIE 数据自动运行 addslashes().不要 ...

  3. C3P0数据库连接池的相关bug解决

    数据库连接池的几个常见bug: 1.警告: com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@76c7022e -- ...

  4. 关于ORALCE一个表空间的数据导入到另一个表空间的方法(原创)

    用户:   whnaproject     所属表空间: whnaproject 新用户   : wniec            所属新表空间: wniec 要求:将用户whnaproject中的数 ...

  5. 黄聪:get_posts 函数 | wordpress

    get_posts 函数,简单的来讲是 get_post 的复数新形势,但因为是文章多篇提取,所以使用方法上却略有不同,支持众多参数选择需要提取的文章,在 CMS 主题中经常被用到,当然如果你对 Wo ...

  6. Objective C SEl 和@selector是怎么工作的||How do SEL and @selector work in iphone sdk?

    SEL is a type that represents a selector in Objective-C. The @selector() keyword returns a SEL that ...

  7. javascript世界一等公民—函数

    简介 在很多传统语言(C/C++/Java/C#等)中,函数都是作为一个二等公民存在,你只能用语言的关键字声明一个函数然后调用它,如果需要把函数作为参数传给另一个函数,或是赋值给一个本地变量,又或是作 ...

  8. cf 605A Sorting Railway Cars 贪心 简单题

    其实就是求总长度 - 一个最长“连续”自序列的长度 最长“连续”自序列即一个最长的lis,并且这个lis的值刚好是连续的,比如4,5,6... 遍历一遍,贪心就是了 遍历到第i个时,此时值为a[i], ...

  9. centos6.5安装mysql记录

    1.查看操作系统相关信息. [root@linuxidc ~]# cat /etc/issue CentOS release 6.5 (Final) Kernel \r on an \m [root@ ...

  10. [实变函数]4.2 Egrov 定理

    1 一致收敛很重要, 但可惜的是很多时候不一致收敛. 比如 $$\bex f_n(x)=x^n\to f(x)=\sedd{\ba{ll} 0,&x\in [0,1)\\ 1,&x=1 ...