V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
leohxj
V2EX  ›  JavaScript

JavaScript一般如何设置时序?

  •  
  •   leohxj · 2013-06-26 22:41:23 +08:00 · 3420 次点击
    这是一个创建于 3928 天前的主题,其中的信息可能已经有所发展或是发生改变。
    比如我想依次执行,除了setTimeout,还有什么方式。
    28 条回复    1970-01-01 08:00:00 +08:00
    Archangel_SDY
        1
    Archangel_SDY  
       2013-06-26 22:50:21 +08:00
    DRcoding
        2
    DRcoding  
       2013-06-26 23:14:10 +08:00
    slixurd
        3
    slixurd  
       2013-06-26 23:16:24 +08:00
    全部用回调?
    tangzx
        4
    tangzx  
       2013-06-26 23:20:21 +08:00 via iPhone
    icedcoffeescript
    zhangxiao
        5
    zhangxiao  
       2013-06-27 03:36:59 +08:00   ❤️ 1
    想省事,直接用async。想学习,自己写个简单的async,原理不难
    zhangxiao
        6
    zhangxiao  
       2013-06-27 03:37:59 +08:00   ❤️ 2
    另外你这个用setTimeout的方法。。不一定能保证依次执行吧。万一其中一个环节执行时间超长
    ijse
        7
    ijse  
       2013-06-27 09:17:03 +08:00
    为什么不喜欢setTimeout?
    ijse
        8
    ijse  
       2013-06-27 09:17:28 +08:00   ❤️ 1
    @zhangxiao 为什么不一定保证依次执行?
    heroicYang
        9
    heroicYang  
       2013-06-27 10:12:09 +08:00   ❤️ 1
    @zhangxiao setTimeout是最能保证依次执行的,而setInterval才不是~
    dorentus
        10
    dorentus  
       2013-06-27 12:30:09 +08:00
    看你对『依次执行』的要求是什么了。

    假如是要『先执行步骤 A,10s 后执行步骤 B,再 5s 后执行步骤 C』这种,那么 setTimeout 就可以胜任:

    A();
    setTimeout(B, 10000);
    setTimeout(C, 15000);

    如果是要『A 执行完毕再执行 B,然后 B 执行完毕再执行 C』,那么就稍微麻烦些,不过用上面大家提到的 async 实现起来应该会简单些。

    PS: window.setInterval 和 window.setTimeout 的唯一区别就是重复执行和只执行一次而已。
    loading
        11
    loading  
       2013-06-27 12:34:37 +08:00 via iPhone   ❤️ 1
    别忘了js响应事件高于一切和单线程本质,你的语句有时会被drop的。不知async会不会发生。
    heroicYang
        12
    heroicYang  
       2013-06-27 13:52:25 +08:00   ❤️ 1
    @dorentus 不仅仅是重复执行和只执行一次的区别...

    @loading setTimeout就不会drop掉耗时久的任务,setInterval才会~
    dorentus
        13
    dorentus  
       2013-06-27 14:09:52 +08:00   ❤️ 1
    @heroicYang Mozilla 和 whatwg 的文档里面都没看到有提到这点么……愿闻其详。
    leohxj
        14
    leohxj  
    OP
       2013-06-27 14:43:44 +08:00
    @dorentus 假如是要『先执行步骤 A,10s 后执行步骤 B,再 5s 后执行步骤 C』这种,除了setTimeout。还有什么优雅一点的方式吗
    dorentus
        15
    dorentus  
       2013-06-27 15:11:56 +08:00   ❤️ 1
    @leohxj 你可以基于它实现自己的优雅的 API 或者队列系统,例如类似 jQuery 的这个:http://api.jquery.com/delay/
    zhangxiao
        16
    zhangxiao  
       2013-06-27 18:41:59 +08:00
    @heroicYang 呃。。没理解你的意思,为啥setTimeout可以保证以此执行。。?
    zhangxiao
        17
    zhangxiao  
       2013-06-27 18:44:38 +08:00   ❤️ 1
    @ijse
    @heroicYang
    其实就是 @dorentus 所说的,要看对依次执行的定义是什么了。如果只是依次触发,那么setTimeout确实可以了。如果是后一个要等前一个完成了再开始,那setTimeout就做不到了
    darasion
        18
    darasion  
       2013-06-27 19:54:04 +08:00   ❤️ 1
    一般来说,事先算出每一步的执行时间,然后在一个循环中分别setTimeout,还要注意闭包问题。原书有bug。


    参考JQuery作者写的:
    《Pro JavaScript Techniques》
    http://book.douban.com/subject/1949853/
    里边有动画的例子。
    heroicYang
        19
    heroicYang  
       2013-06-27 22:27:33 +08:00
    @zhangxiao
    @leohxj
    只有安排好需要执行的任务,不管其中哪个占用大量时间,用setTimeout都是能保证其按顺序执行的。



    当然,如果把任务3的delay time改成比前面任何一个小的话,它肯定是会插入的。

    @dorentus 关于setInterval,可以参看下我以前写的一篇拙文,欢迎拍砖~嘿嘿。 http://heroicyang.com/2012/09/06/javascript-timers/
    zhangxiao
        20
    zhangxiao  
       2013-06-27 22:35:54 +08:00
    @heroicYang 嗯,那我们只是对“依次”的定义或者理解不同。我理解LZ的意思是后一个任务要在前一个任务完成之后才开始。你的理解是只要依次触发即可。
    heroicYang
        21
    heroicYang  
       2013-06-27 22:47:13 +08:00
    @zhangxiao 恩,我理解的这种情况用setTimeout就可以了,你理解的情况用async库的waterfall或者series也可以轻松搞定。就看楼主具体的应用场景了~
    heroicYang
        22
    heroicYang  
       2013-06-27 23:02:42 +08:00
    @zhangxiao 另外,我demo中也是前一个任务完了才执行后一个任务的哦。你吧setTimeout的延时全设成0就知道啦,哈哈。
    zhangxiao
        23
    zhangxiao  
       2013-06-27 23:07:08 +08:00
    @heroicYang 这... 那万一有个异步的调用... 你还是得嵌callback才行了...
    heroicYang
        24
    heroicYang  
       2013-06-27 23:11:52 +08:00
    @zhangxiao 哈哈,那就async走起~
    darasion
        25
    darasion  
       2013-06-28 00:20:12 +08:00
    转一篇 2009 年的文章:
    http://www.laruence.com/2009/09/23/1089.html
    bitsmix
        26
    bitsmix  
       2013-06-28 00:36:22 +08:00
    你们这些争论 setTimeout 真的没看过 javascript 秘密花园或者 the good parts 么
    heroicYang
        27
    heroicYang  
       2013-06-28 10:21:37 +08:00
    @bitsmix 我想这里没有人争论吧?大家只是发表下各自的看法~
    另,如果我没有记错的话, 《The Good Parts》里是没有讲定时器的~
    DaniloSam
        28
    DaniloSam  
       2013-06-30 12:39:05 +08:00
    注意setTimeout是异步的, 并且会受到单线程特性的影响, 所以如果你想精确的10秒后执行, 可能会有惊喜

    算出一个函数的执行时间这事儿, 挺二的, 如果在任何环境执行时间都一样, 世界就没好了

    可以想一下队列这玩意, 参考nodejs里next()如何实现的(想到而已, 卤煮可以看一下)
    如果将你需要按顺序执行的函数 放到一个队列中 每一个执行完都next()一下, 这样根本无需关心某函数的执行时间
    而有新的函数需要进入队列, 直接放到队尾即可
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1939 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 16:23 · PVG 00:23 · LAX 09:23 · JFK 12:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.