JavaScript 中实现 sleep
<table class="d-block"><tbody class="d-block">
<tr class="d-block">
<td class="d-block comment-body markdown-bodyjs-comment-body">
<p align="center"><img alt="来自推特上 Windows 故障分析的笑话" src="https://user-images.githubusercontent.com/3783096/57644343-807f3f80-75ee-11e9-98a4-23123a250d9d.png" style="max-width: 100%"></p>
<p align="center">来自推特上 Windows 故障分析的笑话 图片来源:me.me</p>
<p>推上看到的笑话,Windows 故障分析的实现。</p>
<p>然后想起来 JavaScript 中如何实现这个 <code>sleep()</code> 函数让代码暂停指定时间。</p>
<h2>异步版本</h2>
<p>借助 Promise 这事很好实现。</p>
<div class="highlight highlight-source-js"><pre><span class="pl-k">function</span> <span class="pl-en">sleep</span>(<span class="pl-smi">time</span>) {
<span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-en">Promise</span>(<span class="pl-smi">resolve</span> <span class="pl-k">=></span> {
<span class="pl-c1">setTimeout</span>(() <span class="pl-k">=></span> {
<span class="pl-en">resolve</span>();
}, time);
});
}</pre></div>
<p>创建一个 <code>Promise</code>,等待指定时间后 resolve 掉即可。</p>
<p>但,<code>Promise</code> 是异步的,它要求后续代码要么包含在 <code>then</code> 里面,要么通过 <code>async/await</code> 来调用。</p>
<p>所以使用起来应该像这样子,</p>
<div class="highlight highlight-source-js"><pre><span class="pl-k">function</span> <span class="pl-en">testSleep</span>() {
<span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">"</span>will sleep for 1s<span class="pl-pds">"</span></span>);
<span class="pl-en">sleep</span>(<span class="pl-c1">1000</span>).<span class="pl-c1">then</span>(() <span class="pl-k">=></span> {
<span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">"</span>will sleep for another 5s<span class="pl-pds">"</span></span>);
<span class="pl-en">sleep</span>(<span class="pl-c1">5000</span>).<span class="pl-c1">then</span>(() <span class="pl-k">=></span> {
<span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">"</span>waked up<span class="pl-pds">"</span></span>);
});
});
}
<span class="pl-en">testSleep</span>();</pre></div>
<p>或者这样子:</p>
<div class="highlight highlight-source-js"><pre><span class="pl-k">async</span> <span class="pl-k">function</span> <span class="pl-en">testSleep</span>() {
<span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">"</span>will sleep for 1s<span class="pl-pds">"</span></span>);
<span class="pl-k">await</span> <span class="pl-en">sleep</span>(<span class="pl-c1">1000</span>);
<span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">"</span>will sleep for another 5s<span class="pl-pds">"</span></span>);
<span class="pl-k">await</span> <span class="pl-en">sleep</span>(<span class="pl-c1">5000</span>);
<span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">"</span>waked up<span class="pl-pds">"</span></span>);
}
<span class="pl-en">testSleep</span>();</pre></div>
<p><img src="https://user-images.githubusercontent.com/3783096/57644026-c7b90080-75ed-11e9-86f9-08972d5ef3cb.gif" alt="测试 sleep" style="max-width: 100%"></p>
<p align="center">测试 sleep</p>
<p>当然后者会更加优雅些,但本质上都是需要保证后续代码在 Promise 回调中执行。如何有回调之外的代码,则不会被阻断,这便是其缺点。</p>
<div class="highlight highlight-source-js"><pre><span class="pl-k">async</span> <span class="pl-k">function</span> <span class="pl-en">testSleep</span>() {
<span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">"</span>will sleep for 1s<span class="pl-pds">"</span></span>);
<span class="pl-k">await</span> <span class="pl-en">sleep</span>(<span class="pl-c1">1000</span>);
<span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">"</span>will sleep for another 5s<span class="pl-pds">"</span></span>);
<span class="pl-k">await</span> <span class="pl-en">sleep</span>(<span class="pl-c1">5000</span>);
<span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">"</span>waked up<span class="pl-pds">"</span></span>);
}
<span class="pl-en">testSleep</span>();
<p><span class="pl-c"><span class="pl-c">//</span> 🚨不会按预期那样最后执行,而是立即被执行</span><br>
<span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">"</span>我在等上面的代码执行完...<span class="pl-pds">"</span></span>);</p></pre></div><p></p>
<p><img src="https://user-images.githubusercontent.com/3783096/57644059-e0c1b180-75ed-11e9-8b1a-f511319f2d7c.gif" alt="代码未阻断的情况" style="max-width: 100%"></p>
<p align="center">代码未阻断的情况</p>
<h2>同步版本</h2>
<p>不借助异步异步代码想阻断代码执行,那其实可以让代码原地跑,通过 <code>while</code>。</p>
<div class="highlight highlight-source-js"><pre><span class="pl-k">function</span> <span class="pl-en">syncSleep</span>(<span class="pl-smi">time</span>) {
<span class="pl-k">const</span> <span class="pl-c1">start</span> <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-en">Date</span>().<span class="pl-c1">getTime</span>();
<span class="pl-k">while</span> (<span class="pl-k">new</span> <span class="pl-en">Date</span>().<span class="pl-c1">getTime</span>() <span class="pl-k">-</span> start <span class="pl-k"><</span> time) {}
}</pre></div>
<p>使用起来就和正常函数没区别了,对周围代码也没有要求必需得在回调什么的:</p>
<div class="highlight highlight-source-js"><pre><span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">"</span>start test sync sleep...<span class="pl-pds">"</span></span>);
<span class="pl-en">syncSleep</span>(<span class="pl-c1">3000</span>);
<span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">"</span>sync sleep after 3s<span class="pl-pds">"</span></span>);</pre></div>
<p><img src="https://user-images.githubusercontent.com/3783096/57644100-f9ca6280-75ed-11e9-9291-4ddd0181932a.gif" alt="测试同步版本的 sleep" style="max-width: 100%"></p>
<p align="center">测试同步版本的 sleep</p>
<p>方便是方便,但不建议使用这种方式,毕竟代码在空跑。如果需要这样的场景,你需要考虑是否可以修改下代码或换个设计,异步能满足大部分需求。</p>
<h2>相关资源</h2>
<ul>
<li>MDN - Promise</li>
<li>Synchronous and asynchronous requests</li>
<li>What is the JavaScript version of sleep()?</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
<div id="MySignature" role="contentinfo">
<div>
<img src="https://licensebuttons.net/l/by-nc-sa/3.0/88x31.png" style="vertical-align: middle">
<strong>CC BY-NC-SA 署名-非商业性使用-相同方式共享</strong>
</div><br><br>
来源:https://www.cnblogs.com/Wayou/p/javascript_sleep.html
頁:
[1]