[译] ECMAScript 的 Observables 提案

栏目: JavaScript · 发布时间: 6年前

内容简介:在之前读ps: 在下文中将以 ES 代替 ECMAScript

在之前读 redux 源码时,遇到了关于 Symbol.observable 的使用,发现从没有看到过这个特性,在国内的技术论坛上逛了许久发现提及此的文章甚少,恰巧今天在摸鱼时发现了一篇聊 ECMAScript 中新提案 observables 的文章,故翻译出来加深印象~

原文点此

ECMAScript 中的 Observables 提案

ps: 在下文中将以 ES 代替 ECMAScript

本文介绍的是当前还在ES提案阶段中的observables特性,在下文中通过本文,我们将带你了解该提案,该提案的api,以及一些使用案例

在写下这篇文章的时候, javascriptObservables(观察) 正在通过 RXJs、Bacon.js 等各种类库逐渐普及。Jafar Husain,这位长久以来主张函数式编程的 Netfix 的技术leader(同时也是TC39的委员)也提出了将 observables 集成到我们 js core 中的议案,并且已经通过了 stage1(征求意见阶段) 且已经确定该提案即将进入 stage2(草案阶段)

Observableobserver 的api

在当前提案中, Observable 是一个内建的被用来处理事件流的类, Obsservalbe 的构造函数可以接受一个定义事件流的回调函数。在接下来的例子中,我们的 observable 将只返回值为1或者2的事件流。 observer.next 方法是用来在 observalbe 流中添加事件的:

new Observable(observer => {
    observer.next(1);
    observer.next(2);
})
复制代码

我们也可以使用 observer.error 来记录在流处理时遇到的错误:

new Observable(observer => {
  observer.error(new Error(`Failed to stream events`))
})
复制代码

我们还可以使用 observer.complete 来在流处理完结的时候发出信号:

new Observable(observer => {
  observer.next(1)
  observer.next(2)
  observer.complete()
})
复制代码

传递给我们 Observable 构造函数的这个回调函数会返回一个清理我们Observable实例的方法,它可以执行清理事件监听,定时任务等等类似的清理任务。举个例子,当然这个例子就要比上面这些有趣的多了,他追踪了用户在移动鼠标时,光标相对于页面的位置,并同时产生了描述当前光标坐标的事件流:

function mouseTracking () {
  return new Observable(observer => {
    const handler = ({ pageX, pageY }) => {
      observer.next({ x: pageX, y: pageY })
    }

    document.body.addEventListener(`mousemove`, handler)

    return () =>  {
      document.body.removeEventListener(`mousemove`, handler)
    }
  })
}

复制代码

为了订阅一个 Observable 的事件流,我们会使用 Observable 实例上的 subscribe 方法,这样做会调用我们之前实例化 Observable 时传入的回调函数,绑定事件的监听,并且启动整个事件流。这样做之后我们就能在移动鼠标的时候在事件流里捕获到它啦:

mouseTracking().subscribe({
  next({ x, y }) { console.log(`New position: ${ x }, ${ y }`) },
  error(err) { console.log(`Error: ${ err }`) },
  complete() { console.log(`Done!`) }
})
复制代码

订阅对象上的 unsubscribe

每次订阅我们都会生成一个订阅对象 Subscription ,这个订阅对象上会有一个 unsubscribe 方法让我们用来取消订阅,执行清理方法(我猜大家应该都还记着之前提到的清理函数吧~),当我们不再需要关注观察流里的事件的时候,just unsubscribe it,让我们将其解放吧。

const subscription = mouseTracking().subscribe({
  next({ x, y }) { console.log(`New position: ${ x }, ${ y }`) },
  error(err) { console.log(`Error: ${ err }`) },
  complete() { console.log(`Done!`) }
})

subscription.unsubscribe()
复制代码

Observable.of

Observable.of(...items) 是一个简单有效的能帮助我们从提供的 items 中创建 Observable 的方法,在使用了 Observable.of 方法之后, items 生成的 Observable 实例会在调用 subscribe 的同时生成事件流,返回 items 中的 value

Observable.of(1, 2, 3, 4).subscribe({
  next(item) { console.log(item) }
})
// <- 1
// <- 2
// <- 3
// <- 4
复制代码

我们甚至可以认为, Observable.of 可以理解为跟以下接受一个入参,然后回传事件流的简单例子一样:

Observable.of = (...items) => {
  return new Observable(observer => {
    items.forEach(item => {
      observer.next(item)
    })
    observer.complete()
  })
}
复制代码

Observable.from

Observable.from 静态方法接受一个类型为对象的入参,如果这个对象中有键值为 Symbol.observable 的方法,那么就会返回这个方法的返回值。

Observable
  .from({
    [Symbol.observable]() { return Observable.of(1, 2, 3) }
  })
  .subscribe({
    next(item) { console.log(item) }
  })
// <- 1
// <- 2
// <- 3
复制代码

当然如果这个传入的对象没有实现 Symbol.observable ,那么我们就假定其传入的是一个可迭代的元素, Observable.from 在这个时候的作用就是将迭代元素遍历并生成一个 Observable 实例,依次将被遍历的结果放入事件流中:

Observable
  .from([1, 2, 3])
  .subscribe({
    next(item) { console.log(item) }
  })
// <- 1
// <- 2
// <- 3
复制代码

在这种情况下,我们的 Observable.from 实现的功能和 Observable.of 是类似的,据此我们甚至可以这样去理解 Observable.from 的实现:

Observable.from = value => {
  if (typeof value[Symbol.observable] === `function`) {
    return value[Symbol.observable]()
  }
  return Observable.of(Array.from(value))
}
复制代码

结语

虽然现在这个提案还在襁褓之中,但是我相信迟早有一天,其会成为 javascript 的函数式编程的基石。到那天,我相信它还会具有类似 filtermap 的能力去处理我们的事件流,让我们在庞大的事件流能够仅仅注重我们需要关注的部分就够了

与此同时,我们的代码格式和开发模式也能在其帮助下变得更加的自然和规范,当然你也可以提前使用我们在github上的的 polyfill 去提前体验它,但是请切记在浏览器环境下删除掉你的 export 关键字。

多个嘴

作为一个英语不是很好的码农,翻译本文还是有点磕磕碰碰,但是总算还是勉勉强强搞定了,希望能够帮助大家多了解一下这个特性,如有错误麻烦诸位指出一下,最后国际惯例,感谢各位的阅读~


以上所述就是小编给大家介绍的《[译] ECMAScript 的 Observables 提案》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Effective Engineer

The Effective Engineer

Edmond Lau / The Effective Bookshelf, Palo Alto, CA. / 2015-3-19 / USD 39.00

Introducing The Effective Engineer — the only book designed specifically for today's software engineers, based on extensive interviews with engineering leaders at top tech companies, and packed with h......一起来看看 《The Effective Engineer》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试