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

2016-06-20 21:11:25 +08:00
 Kilerd

现在我有一个需求是

有 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 ,所以没办法, 做一次伸手党吧。

4325 次点击
所在节点    问与答
15 条回复
bdbai
2016-06-20 21:29:56 +08:00
js 该异步还得异步。对抗 callback hell 的方法挺多的,比如:
Promise 大法,把回调函数铺平;
co / async await 大法,执行多个异步任务同时维持作用域,很爽的用法。
当然这样或多或少都要引入别的库,甚至需要预处理器。看你喜好啦。
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
2016-06-20 21:55:58 +08:00
问下你怎么格式化代码的?
iwege
2016-06-20 21:56:44 +08:00
babel await async 或者 promise 。
Kilerd
2016-06-20 22:01:38 +08:00
@bdbai @iwege 我在看 promise

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

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

毕竟这个项目很小,只要解决完这个 异步的问题,剩下的一两天估计就完事了。
klesh
2016-06-20 22:16:16 +08:00
bdbai
2016-06-20 22:21:54 +08:00
@Kilerd 教程网上搜一下就有。目前支持 async/await 的浏览器还不够多,所以需要用 Babel 转换到普通代码。
sensui7
2016-06-20 22:52:31 +08:00
加个 flag,其他操作检测一下是否显示了.
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
2016-06-20 23:23:38 +08:00
不能,必须从 javascript 返回,把控制权交还给浏览器,浏览器才能给你渲染页面。
Pastsong
2016-06-20 23:42:51 +08:00
SetTimeout 本身也是异步啊

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/287131

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX