Promise 与定时器

ECMAScript 6 的 Promise 是一个非常重要的特性,有了它,JavaScript 异步嵌套的问题算是得到了比较好的解决。同时,Promise 也是 ES7 中 async/await 的基础。

promise

介绍 Promise 基础的文章已经非常多了,在这里就不再讲解 Promise 本身的用法。本文主要介绍利用 Promise 的特性改良异步 Timer 的一种思路。

在产品中,异步加载资源的时候,有时会有一种业务需求,需要执行某个任务,直到任务返回 false 或者超过某个时间限制。

例如,在 360网址导航 中,存在类似这样的代码:

这里的 qboot.await 实际上是一个异步的 timer,由于导航网页上的部分内容是异步加载的,因此用 qboot.await 来确保操作相关 DOM 的时候内容已经加载完毕。

qboot 的具体代码在 github 上可以找到。这里截取其中的片段:

await 方法虽好,但是不够语义化,在这个支持 Promise 的时代,实现这个需求,我们可以有更好的设计思路,产生更加 语义化 的 API:

wait-promise 库

我们可以基于 Promise 实现一套优雅的 API,把它封装成 wait-promise 库。

根据常见应用场景设计如下 API:

check

wait.check(condition)

check 总是返回一个 promise,如果 condition 抛出未处理的异常或者返回一个 false 值,那么 promise 的状态为 reject,否则 resolve 该 promise。

例如:

until

wait.until(condition)

until 每隔若干时间间隔(默认为100ms),检查一次 condition,直到当前 condition 不抛异常也不返回 false 值为止,满足条件后将 promise 的状态置为 resolve。

例如:

ES7 的用法:

till

wait.till(condition)

until 类似,不同之处在于 condition 返回 true 的时候 till 将 promise 的状态置为 resolve。同样与 until 相反,如果 till 的 condition 抛异常, promise 的状态为 reject 。

例如(通常情形下和 until 用法一样):

before

wait.before(millisec).until(condition)

before 通常和 until 组合使用,给 until 轮询限制一个最长时间,超过时间之后,如果 condition 还是抛异常或者返回 false,则将 promise 的状态置成 reject。

例如:

通常我们可以用来判断资源是否加载成功(包含超时):

after

wait.after(millisec).check(condition)

after 通常和 check 组合使用,超过一定时间之后再执行 condition 检查。

例如:

after 也可以和 util 组合使用,因为 wait.util 第一次总是会尽快执行(然后才是每经过固定时间间隔执行一次),所以使用 after 可以让 until 第一次执行也延迟。

例如:

limit

wait.limit(n).until(condition)

before 类似,不过 limit 是限制 condition 的执行次数而不是时间。

例如:

every

wait.every(millisec[, limit]).until(condition)

every 的作用是改变 condition 检查的时间间隔。

例如:

every(millisec, limit)every(millisec).limit(limit) 的简写。

例如:

sleep

wait.sleep(millisec)

什么也不做,等待一定的时间。实际上 sleep 是等价于 wait.after(millisec).check();

例如:

ES7 里面使用起来更顺。

例如:

具体实现

实际上,基于 Promise 实现上述 API 很简单,逻辑较复杂的只有 until 方法,check 方法甚至直接可以用 wait.before(0).until(cond) 来表示,其他的方法也都只是设置一些参数和链式传递。具体实现代码见下方。

wait-promise.js 代码

总结

基于 Promise 我们用不到 100 行代码实现了增强的定时器 API,拥有自然语言风格的表达,非常的语义化和容易使用。事实上我将它结合 mochachai 写单元测试用例,在构造异步的用例上,它使得测试用例的代码看起来非常的优雅:

测试代码1:

对应的测试用例:

测试代码2:

对应的测试用例:

你可以来尝试使用它,使用方法非常简单,只需要将下面的 js 加入你的页面:

它支持 AMD 加载和独立加载。对于不支持 ES6 Promise 的浏览器,我们可以使用 polyfill 轻松解决。

最后,这个项目的地址是:https://github.com/akira-cn/wait-promise

打赏支持我写出更多好文章,谢谢!

打赏作者

打赏支持我写出更多好文章,谢谢!

任选一种支付方式

1 4 收藏 评论

关于作者:十年踪迹

月影,奇舞团团长,热爱前端开发,JavaScript 程序猿一枚,能写代码也能打杂卖萌说段子。 个人主页 · 我的文章 · 14 ·     

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部