Open xxleyi opened 3 years ago
要求:
1、只能修改 setTimeout 到 Math.floor(Math.random() * 1000 的代码
setTimeout
Math.floor(Math.random() * 1000
2、不能修改 Math.floor(Math.random() * 1000
3、不能使用全局变量
function print(n){ setTimeout(() => { console.log(n); }, Math.floor(Math.random() * 1000)); } for(var i = 0; i < 100; i++){ print(i); }
解:
看原帖中的解答,除了一个回答之外,都在利用 trick 绕过随机延迟,但也有人疑惑:题目本意应该不是如此。有一位大神也给出了一个保留原来随机延迟的解答。但写法太过妖娆,看不大明白。
在昨晚看到这个题之后,百思不解之下,我就睡觉了。今早睡醒,躺在床上想了想,突然就悟了:这就是要把异步并发改为异步串行啊!
那就队列走起,Promise 走起,布尔控制变量走起呗?
什么?不允许使用全局变量?那就函数属性走起呗,反正函数也是对象,大不了干完活我再删除相关属性。我悄悄的来,悄悄的走。
基本思路:for 循环入队异步任务,入队结束后,触发异步任务顺序执行。
代码如下:
// 为了调试方便,改成 10 个数,随机时间小于 100ms function print(n, reverse = false) { setTimeout((t) => { print.times = print.times || [] print.delay = print.delay || [] print.trigger = print.trigger || false print.times.push(t) print.delay.push(() => { // 加个 reverse 参数控制异步队列执行顺序,虽然表面上违背了题目要求,但精神上应该没有,大不了硬编码 const next = n + (reverse ? -1 : 1) new Promise(resolve => { console.log("delay", print.times[n]) setTimeout(() => { console.log(n) resolve() }, print.times[n]) }).then(() => { if (print.delay[next]) { print.delay[next]() } else { delete print.times delete print.delay delete print.trigger } }) }) if (print.trigger) { } else { // 所有异步任务都入队之后,再触发异步队列的执行,从头到尾,或从尾到头 setTimeout(() => print.delay[reverse ? print.delay.length - 1 : 0]()) // 保证只 trigger 一次 print.trigger = true } }, 0, Math.floor(Math.random() * 100)); } for(var i = 0; i < 10; i++){ print(i); }
总结:这样能按照给定延迟时间在逻辑上顺次执行。但也有一个缺陷:如果罗列多个循环,会产生调度问题。但超出此题目范围,只能根据具体问题来解决了,说不定真实需求下,就是只用一次呢?哈哈哈。
要求:
1、只能修改
setTimeout
到Math.floor(Math.random() * 1000
的代码2、不能修改
Math.floor(Math.random() * 1000
3、不能使用全局变量
解:
看原帖中的解答,除了一个回答之外,都在利用 trick 绕过随机延迟,但也有人疑惑:题目本意应该不是如此。有一位大神也给出了一个保留原来随机延迟的解答。但写法太过妖娆,看不大明白。
在昨晚看到这个题之后,百思不解之下,我就睡觉了。今早睡醒,躺在床上想了想,突然就悟了:这就是要把异步并发改为异步串行啊!
那就队列走起,Promise 走起,布尔控制变量走起呗?
什么?不允许使用全局变量?那就函数属性走起呗,反正函数也是对象,大不了干完活我再删除相关属性。我悄悄的来,悄悄的走。
基本思路:for 循环入队异步任务,入队结束后,触发异步任务顺序执行。
代码如下:
总结:这样能按照给定延迟时间在逻辑上顺次执行。但也有一个缺陷:如果罗列多个循环,会产生调度问题。但超出此题目范围,只能根据具体问题来解决了,说不定真实需求下,就是只用一次呢?哈哈哈。