javascript 脚本如何进行“等待/sleep()”?

2015-11-10 14:41:40 +08:00
 leavic
最近在学 js ,拿几个网站写 grease monkey 脚本练手,发现一个问题是有些网站的数据并不是直接在 html 中呈现的,而是通过 js 加载的,也许这就是所谓的 ajax 吧。

现在问题是,如果我要用自己的脚本处理这部分数据,就必须保证这些数据被网站自己的脚本加载成功了才行,否则我的脚本是看不到这些数据的。

因为 ajax 很多都是异步加载的,所以就算是把函数绑定到 windows.onload 方法上也不一定能保证脚本加载完了数据,现在的方法只能是用 setTimeOut 做个固定延时,但体验不太好,而且不是稳妥的做法。

我希望的做法是用一个 while 循环检查页面内容是否加载成功,这个循环中,如果没有检测到内容,就让 js 脚本睡眠,类似 rtos 中线程主动释放 cpu 控制权一样。否则的话,这个循环就是个一直占用大量 CPU 资源的恶性循环,很容易让浏览器假死。

不过找了一圈好像没有看到这样的函数,我总不能为了实现个 sleep ,自己在 javascript 上写一套类 rtos 调度系统出来吧。我本来想用一堆10~100毫秒的setTimeOut来实现,结果发现这好像还是会让浏览器假死,似乎setTimeout并没有释放CPU资源。
15529 次点击
所在节点    JavaScript
39 条回复
iamcho
2015-11-10 14:50:17 +08:00
.done()
phithon
2015-11-10 14:51:52 +08:00
学 javascript ,心里必须有“回调函数”的概念。
比如你进行的 ajax 操作,需要等待服务端返回包再处理数据。
那你应该把处理数据的代码放在 ajax 的回调函数里,而不是像其他同步语言一样写在 ajax 代码后一行。
leavic
2015-11-10 14:52:28 +08:00
@iamcho 请问这是 jQuery 里的函数吗?有没有纯 js 的实现?
leavic
2015-11-10 14:55:44 +08:00
@phithon 我写的是 grease monkey 脚本,和网站服务器是独立的两个部分,网站的 ajax 操作,怎么能设置我的函数作为回调呢?
BTW ,抛开回调的概念,难道就没有这种方法吗?因为交出 cpu 控制权做一个简单的 sleep ,这几乎在所有语言里都有,就算在 C 里也很容易实现。
zzNucker
2015-11-10 15:01:25 +08:00
@leavic JS 你还想让它交出 CPU 控制权,你想让浏览器 block 么
ericls
2015-11-10 15:02:16 +08:00
js 是 non-blocking 是单线程的,如果你 sleep 了 那全部都会 block 住。。。
coolicer
2015-11-10 15:03:49 +08:00
@leavic 浏览器如果有这个 sleep 应该会把界面卡住吧,所以没发现可以这样。可以用一下 es6 的生成器,可以暂停 /重新 执行函数。
ChefIsAwesome
2015-11-10 15:12:03 +08:00
你光用 setTimeOut 怎么可能让浏览器假死
frozen2013
2015-11-10 15:13:33 +08:00
之前某墙攻击 github 的方法也是 setTimeout 来实现的,从没有人说那段循环加载导致引用那段 js 的网页死掉啊。 http://drops.wooyun.org/papers/5398
恐怕你在 setTimeout 引的 function 里做了太多耗时的计算工作了,你可以用 settimeout 来循环检查是某资源否加载完毕,确定加载完毕后再去做其他耗时的计算工作。
hronro
2015-11-10 15:16:25 +08:00
xmhttp.onreadystatechange = function(){

}
hronro
2015-11-10 15:19:01 +08:00
我字还没打完怎么就发出去了
XMLHttp.onreadystatechange = function(){
if(XMLHttp.readyState==4 && XMLHttp.status==200){
//这里填完成数据加载后执行的内容
}
};
Cloudee
2015-11-10 15:20:45 +08:00
你是不是在 while 里面 setTimeout 了……你在函数的最后 setTimeout 这个函数自己。
或者不用 while 循环用 setInterval
hronro
2015-11-10 15:21:31 +08:00
js 是单线程,但是可以是异步的。像 AJAX 就是典型的异步执行
leavic
2015-11-10 15:23:09 +08:00
@ChefIsAwesome

while(True)
{
if(check_something()==False)
{
setTimeOut(nop_function,100)
}
}


执行到这段明显卡住了,我希望的是 check_something 为 false 之后就 sleep 100 毫秒,这样占用的 CPU 时间顶多是有限次的 check_something()函数的执行时间,但实际看来并不是这样。
leavic
2015-11-10 15:24:20 +08:00
@frozen2013 我就是做了个很简单的 a=2,if(a==1) alert('something'),基本上只有一个赋值和一个判断命令会被使用,我就把这段话当 nop 用了。
hronro
2015-11-10 15:24:46 +08:00
@leavic JS 里应该没有 sleep 这样的东西
breeswish
2015-11-10 15:25:47 +08:00
alert 会阻塞
leavic
2015-11-10 15:26:04 +08:00
@Cloudee 是的,我不是很清楚 setTimeOut 的工作方式,我以为这个函数可以实现非 block 的 sleep
Cloudee
2015-11-10 15:29:14 +08:00
@leavic 不是这样, setTimeout 是立即返回,并且在调度队列里面加上一个 n 毫秒后的任务,所以相当于你这个在不停地执行,并且不停地往调度队列里面添加新的任务。你的这个需求可以考虑用 setInterval ,并在函数体里面判断条件是不是满足,不满足就直接返回,满足再执行里面的逻辑。
leavic
2015-11-10 15:30:44 +08:00
@Cloudee 对,我刚刚想明白这点,这样可以解释为什么 while 会卡死了, setTimeOut 对 CPU 来说和其他语句是一样的。我确实该试试 setInterval ,谢谢!

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

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

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

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

© 2021 V2EX