JavaScript 最新特性实现的三大黑科技
oulaly
7年前
<h2>依次执行多项异步任务</h2> <p>有时候,我们希望批量执行一组异步任务,但是不是 <strong>并行</strong> ,而是依次执行,这组任务是动态的,在一个数组里,当然我们可以用 for 循环然后一个一个 await 执行,但是还有另外一种方式:</p> <p><a href="/misc/goto?guid=4959749928385917170" rel="nofollow,noindex">JS Bin on jsbin.com</a></p> <p>在上面的例子里,我们定义了一个 taskReducer:</p> <pre> <code class="language-javascript">async function taskReducer(promise, action){ let res = await promise; return action(res); }</code></pre> <p>这个 reducer 的两个参数是 promise 和 action,promise 是代表当前任务的 promise,而 action 是下一个要执行的任务。我们可以 await 当前 promise 执行当前任务,然后将执行结果传给下一个 action 就可以了。</p> <p>这样我们可以调用:</p> <pre> <code class="language-javascript">[task1, task2, task3, ...].reduce(taskReducer, init);</code></pre> <p>不管这些任务是同步还是异步都可以被 <strong>依次执行</strong> 。需要注意的是,每一个任务的返回值将是下一个任务的输入 promise 或者 value。</p> <h2>generator 与 async/await 一同使用</h2> <p>将上面的代码进一步扩展,我们发现,它可以支持 generator 与 async/await 一同使用:</p> <p><a href="/misc/goto?guid=4959749928482742813" rel="nofollow,noindex">JS Bin on jsbin.com</a></p> <p>在上面的例子里,我们定义了一个计时 tick 函数,我们通过 timing 来连续调用它,而 timing 是一个 generator,计时器显然是异步函数,然而我们可以:</p> <pre> <code class="language-javascript">continuous(...timing(10))(0);</code></pre> <p>而这里的 continuous 其实就是前面的 reduce 的封装。</p> <h2>使用 Proxy 实现 PHP 中的常用“魔术方法”</h2> <p>PHP 中有 __get 、 __set 和 __call 三个强大的魔术方法,可以实现对不存在的属性的读写和方法调用。在新的 ES 标准中添加了 Proxy 类,它可以构造 Proxy 对象,用来“重载”对象的属性和方法读写,从而实现类似于 PHP 的魔术方法:</p> <p><a href="/misc/goto?guid=4959749928551979319" rel="nofollow,noindex">JS Bin on jsbin.com</a></p> <p>上面的例子里,我们在对象构造的时候,分别“代理”对象实例的属性 get 和 set 方法,如果对象上已存在某个属性或方法,代理直接返回或操作该属性。否则,判断对象上是否有 __get 、 __set 或者 __call 方法,有的话,做相应的处理。</p> <p>这里我们使用装饰器模式,定义了一个 Magical 装饰器函数,让它来处理希望使用 Magical 的类。</p> <p>等到 <a href="/misc/goto?guid=4959643070687769896" rel="nofollow,noindex">ES Decorators</a> 标准化了之后,我们就可以使用更加优雅的写法了:</p> <pre> <code class="language-javascript">@magical class Foo { __call(key, ...args){ ... } }</code></pre> <p>以上就是今天的所有内容。ES 的新特性为我们提供了非常强大的功能,让我们能够更加优雅地写代码。有任何问题,欢迎留言讨论。</p> <p> </p> <p>来自:https://www.h5jun.com/post/three-black-tech-in-modern-js.html</p> <p> </p>