V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
Kilerd
V2EX  ›  问与答

Javascript 能不能纯粹的同步方式执行代码?

  •  
  •   Kilerd · 2016-06-20 21:11:25 +08:00 · 4327 次点击
    这是一个创建于 3079 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在我有一个需求是

    有 N 组数据,每组三个数字 x,y,z
    
    按顺序显示内容, x 显示 1000ms, 休息 250ms , y 显示 1000ms, 休息 250ms , z 显示 1000ms
    

    又因为有某种原因,只能用 web 写,所以只能用没写过的 javascript 假设现在有一个 <div class=box></box>

    我最初写的代码是这样的

    // 网上找的 sleep 代码
    function sleep(n){
            var  start=new Date().getTime();
            while(true) if(new Date().getTime()-start>n)  break;
        }
        
        $(".box").html(x)
        sleep(1000)
        $(".box").html("")
        
        $(".box").html(y)
        sleep(1000)
        $(".box").html("")
        
        $(".box").html(z)
        sleep(1000)
        $(".box").html("")
        
    

    实验证明, 他会卡死在最开始的界面,然后时间到了就没了。 这样可以做到延时,可是显示的效果没有出来,弃。

    jquery.delay() 只对动画效果有效,弃

    所以现在采用的是 setTimeout 的方法

    $(".box").html(x)
        setTimeout(function(){
        	$(".box").html("")
        }, 1000)
        
        setTimeout(function(){
        	 $(".box").html(y)
        }, 1250)
       
       setTimeout(function(){
        	$(".box").html("")
        }, 2250)
    	....
    

    这样可以实现,然后如果多组数据的话也可以用一个变量来记录延时的时间值

    假如我把上面的代码封装成一个函数display() 那么接下来我的代码就会显得很干噶

    display()
    
    do something....
    

    后面的代码就会在数字显示完成之前执行了。 也就是说,如果我一个地方出现了setTimeout 其他地方就得被迫无奈地都用上。 即

    display()
    
    setTimeout(function(){
    	do something...
    }, display()所延时的时间).
    

    So. 有没有一种像最开始的那种方案来解决这个问题??

    PS : 我不会写 JS ,所以没办法, 做一次伸手党吧。

    15 条回复    2016-06-20 23:42:51 +08:00
    bdbai
        1
    bdbai  
       2016-06-20 21:29:56 +08:00 via Android
    js 该异步还得异步。对抗 callback hell 的方法挺多的,比如:
    Promise 大法,把回调函数铺平;
    co / async await 大法,执行多个异步任务同时维持作用域,很爽的用法。
    当然这样或多或少都要引入别的库,甚至需要预处理器。看你喜好啦。
    klesh
        2
    klesh  
       2016-06-20 21:54:37 +08:00
    function display(array, cb) {
    var index = -1, length = array.length, $elem = $('.box');
    while (++index < length) {
    (function(html){
    setTimeout(function() {
    $elem.html(html)
    }, index * 1000);
    })(array[index]);
    }
    setTimeout(cb, index * 1000);
    }

    display([
    'a',
    'b',
    'c'
    ], function() {
    console.log('done');
    })
    klesh
        3
    klesh  
       2016-06-20 21:55:58 +08:00
    问下你怎么格式化代码的?
    iwege
        4
    iwege  
       2016-06-20 21:56:44 +08:00
    babel await async 或者 promise 。
    Kilerd
        5
    Kilerd  
    OP
       2016-06-20 22:01:38 +08:00
    @bdbai @iwege 我在看 promise

    @klesh 哇,真的很感动,居然真的去写代码了, 不过这个是从工程里面抽出来的一个例子而已。

    代码格式化只能在发帖的时候用,回复是不行的,只能用 gist 解决
    bdbai
        6
    bdbai  
       2016-06-20 22:04:47 +08:00 via Android
    @klesh 启用 Markdown 的帖子内容用 ``` 格式包裹代码就可以。评论不支持 Markdown ,但可以贴 Gist 链接。
    klesh
        7
    klesh  
       2016-06-20 22:07:17 +08:00
    噢,原来如此。 V2EX 编辑器太挫了。起码支持下 markdown 嘛。
    bdbai
        8
    bdbai  
       2016-06-20 22:09:14 +08:00 via Android
    @Kilerd 发重了...
    async/await 写起来比较顺手,不会像 Promise 那样打断作用域。如果有兴趣可以尝尝鲜。
    Kilerd
        9
    Kilerd  
    OP
       2016-06-20 22:15:33 +08:00
    @bdbai 有什么靠谱的教程吗? 或者什么类似的轻框架上手即用的。

    毕竟这个项目很小,只要解决完这个 异步的问题,剩下的一两天估计就完事了。
    klesh
        10
    klesh  
       2016-06-20 22:16:16 +08:00
    bdbai
        11
    bdbai  
       2016-06-20 22:21:54 +08:00 via Android
    @Kilerd 教程网上搜一下就有。目前支持 async/await 的浏览器还不够多,所以需要用 Babel 转换到普通代码。
    sensui7
        12
    sensui7  
       2016-06-20 22:52:31 +08:00
    加个 flag,其他操作检测一下是否显示了.
    vc1
        13
    vc1  
       2016-06-20 23:03:42 +08:00
    https://github.com/caolan/async

    var q = async.queue(function (task, next) {
    document.body.innerHTML = task.data;
    setTimeout(next, task.time);
    });

    q.push([{data: 'a', time:1500}, {data: 'b', time:500}, {data: 'c', time:3000}, {data: 'd', time:0}]);
    billlee
        14
    billlee  
       2016-06-20 23:23:38 +08:00
    不能,必须从 javascript 返回,把控制权交还给浏览器,浏览器才能给你渲染页面。
    Pastsong
        15
    Pastsong  
       2016-06-20 23:42:51 +08:00 via Android
    SetTimeout 本身也是异步啊
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3019 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 13:48 · PVG 21:48 · LAX 05:48 · JFK 08:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.