Web3JS文档速读 (4)完美推送体验之Subscribe

Subscribe 目的是消息订阅, 目前经过测试, subscribe 不支持 http(s), 只支持使用 wss 的连接. - IPC 自有节点没有测试.

消息的订阅与取消

订阅消息

1
2
3
4
const subscription = eth.subscribe(type, options)
.on("data", log => {})
.on("changed", log => {})
.on("error", err => {})
  • type: pendingTransactions, newBlockHeaders, syncing, logs 四种类型之一.
  • options: 只有type 为 logs 监听日志的时候才需要.
  • data: 在有数据消息时触发
  • changed: 在数据变更时触发, 带有额外字段 "removed": true, 只有监听日志和同步状态的时候才有.
  • error: 出错的时候触发

取消订阅

1
2
3
4
5
// 取消指定的
subscription.unsubscribe((err, success) => {});

// 取消所有
eth.clearSubscriptions();

不同的事件, data 数据结构不同~

pendingTransactions 正在发生的交易.

newBlockHeaders 产生新区块.

syncing 节点是否处于同步状态.

logs 监听事件日志.

简单介绍一下 changed 事件中的 "remove":true

在监听 log 事件的时候, 会有 changed 事件返回一条标记为 "remove":true.

在 web3 的文档中并没有解释该内容为什么会标记为被删除.

经过几天的测试, 发现标记为删除状态的日志有一个共同的特点, 那就是会出现重复记录:

1
2
3
[2018-07-06T15:27:01.349] data {"address":"0x081e9864de79CC6451B5086d5131a522CFAe353B","topics":["0x4c04faa490e5760276d4c93311b52cbdcee13446ac39b892ffe3c7c129e214e3"],"data":"0x4659447235556b4a4864736b545679000000000000000000000000000000000000000000000000000000000000000000000000000000000190ca5efcb9480000","blockNumber":2589009,"transactionHash":"0xf79031d69c54d37e7d3bc47176161c3732a7be2d961d2f310889e8c79853d1ec","transactionIndex":7,"blockHash":"0x2fe1a0bc356bccdcccf9aa61e4d04403d869cbdd14dbc09994373aae77f9e60c","logIndex":9,"removed":false,"id":"log_e80adc5f"}
[2018-07-06T15:27:01.399] data {"address":"0x081e9864de79CC6451B5086d5131a522CFAe353B","topics":["0x4c04faa490e5760276d4c93311b52cbdcee13446ac39b892ffe3c7c129e214e3"],"data":"0x4659447235556b4a4864736b545679000000000000000000000000000000000000000000000000000000000000000000000000000000000190ca5efcb9480000","blockNumber":2589009,"transactionHash":"0xf79031d69c54d37e7d3bc47176161c3732a7be2d961d2f310889e8c79853d1ec","transactionIndex":5,"blockHash":"0xab7537cbcd19a7bf494de4053ba8ac7b0c9038cfe03592bfec7385e84566f2b8","logIndex":7,"removed":false,"id":"log_eb7e1506"}
[2018-07-06T15:27:01.408] changed {"address":"0x081e9864de79CC6451B5086d5131a522CFAe353B","topics":["0x4c04faa490e5760276d4c93311b52cbdcee13446ac39b892ffe3c7c129e214e3"],"data":"0x4659447235556b4a4864736b545679000000000000000000000000000000000000000000000000000000000000000000000000000000000190ca5efcb9480000","blockNumber":2589009,"transactionHash":"0xf79031d69c54d37e7d3bc47176161c3732a7be2d961d2f310889e8c79853d1ec","transactionIndex":7,"blockHash":"0x2fe1a0bc356bccdcccf9aa61e4d04403d869cbdd14dbc09994373aae77f9e60c","logIndex":9,"removed":true,"id":"log_e80adc5f"}

上面的内容, 是在 rinkeby 网络的真实数据, 首先收到了一条 data 事件的数据, 然后紧接着又收到一条 data 数据, 之后收到一条 changed 数据. 几条数据几乎是同时触发.

查阅了一些文字内容:

官方的 Wiki:

removed: TAG - true when the log was removed, due to a chain reorganization. false if its a valid log.

Ethereum StackExchange 的一个则直接给例子和注释

1
2
3
.on('changed', function(event){
// remove event from local database
})

Ethereum event log removed field 专门介绍 Event 的 Removed 字段

从源代码注释中, 给出的解释大致为: data 事件获取的数据, 在交易处在 pending 状态下的时候就抛出了, 当出现某些交易失败(本交易或本交易前的其他交易), 那么对应的 log 就会有相应的变动, 会使用 data 事件重新发送新的 log, 并且使用 changed 事件抛出原有 log 并标记为 "removed": true.

Donate - Support to make this site better.
捐助 - 支持我让我做得更好.