Promise 与定时器

1011 查看

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。

例如:

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