https://github.com/kumavis/sw-stream

ServiceWorkerStream and ServiceWorkerGlobalListener

This a utility for creating streams between the page and a servive worker.

在页面也服务器中创建流

usage

in page

pass the registered service worker to create a duplex stream.

传递一个登录的service worker去创建一个双工流

const duplex = SwStream({ serviceWorker: this.serviceWorker.controller })
 

There is an optional context property that will be passed along on the initial handshake and retreivable from the messageEvent.data.context received from the SwGlobalListener.

context参数是可选的,它将会在第一次握手时传递并且会被从SwGlobalListener检索得到的messageEvent.data.context检索到

const duplex = SwStream({ serviceWorker, context })
 
in ServiceWorker

listen for client connections

const connectionListener = new SwGlobalListener(self)

connectionListener.on('remote', (portStream, messageEvent) => {
// ...
})

看测试了解使用:

sw-stream/test/service-worker.js (即background.js)

const SwGlobalListener = require('../lib/sw-global-listener')
const swGlobal = self // setup ServiceWorkerGlobal and capture clients swGlobal.addEventListener('activate', function(event) {
event.waitUntil(swGlobal.clients.claim())
}) swGlobal.oninstall = function (event) {
event.waitUntil(swGlobal.skipWaiting())
} // listen for clients const connectionListener = new SwGlobalListener(swGlobal) connectionListener.on('remote', (portStream, messageEvent) => {
console.log('got a remote connection!')
remoteStream.on('data', (message) => {
console.log('message:', message)
// example: double value and then send back
let newValue = message.value *
remoteStream.write({ value: newValue })
})
})

sw-stream/lib/sw-global-listener.js

const EventEmitter = require('events')
const PortStream = require('./message-channel-port-stream') class SwGlobalListener extends EventEmitter { constructor (swGlobal) {
super()
swGlobal.addEventListener('message', (messageEvent) => {
// validate port
if (!messageEvent.data) return
if (messageEvent.data.action !== 'handshake') return
// process message
const port = messageEvent.ports[]
if (!port) throw new Error('Handshake missing port...')
// create new portStream
const portStream = new PortStream(port)
// announce new connection
this.emit('remote', portStream, messageEvent)
})
} } module.exports = SwGlobalListener

sw-stream/lib/message-channel-port-stream.js

const Duplex = require('readable-stream').Duplex
const inherits = require('util').inherits module.exports = MessageChannelPortDuplexStream inherits(MessageChannelPortDuplexStream, Duplex) function MessageChannelPortDuplexStream (port) {
Duplex.call(this, {
objectMode: true,
})
this._port = port
port.onmessage = this._onMessage.bind(this)
} // private MessageChannelPortDuplexStream.prototype._onMessage = function (event) {
const msg = event.data
if (Buffer.isBuffer(msg)) {
delete msg._isBuffer
var data = new Buffer(msg)
this.push(data)
} else {
this.push(msg)
}
} // stream plumbing MessageChannelPortDuplexStream.prototype._read = noop MessageChannelPortDuplexStream.prototype._write = function (msg, encoding, cb) {
try {
if (Buffer.isBuffer(msg)) {
var data = msg.toJSON()
data._isBuffer = true
this._port.postMessage(data)
} else {
this._port.postMessage(msg)
}
} catch (err) {
return cb(new Error('MessageChannelPortDuplexStream - disconnected'))
}
cb()
} // util function noop () {}

sw-stream/test/sw-launcher.js

const EventEmitter = require('events')
const SwStream = require('../lib/sw-stream') module.exports = class ServiceWorkerLauncher extends EventEmitter {
constructor (opts) {
super()
this.serviceWorker = navigator.serviceWorker
this.startWorker()
.then(registeredWorker => {
console.log('setting up stream...')
const duplex = SwStream(registeredWorker)
duplex.on('data', (chunk) => {console.log('controller saw:', chunk) })
duplex.on('error', (chunk) => {console.log('controller saw:', chunk) })
duplex.write({ value: })
})
.catch(err => {
this.handleError(err)
})
} startWorker () {
// check to see if their is a preregistered service worker
if (!this.serviceWorker.controller) {
console.log('registering...')
return Promise.resolve(this.registerWorker())
} else {
console.log('ready')
return Promise.resolve(this.serviceWorker.ready)
}
} registerWorker () {
return this.serviceWorker.register('sw-bundle.js')
.then(sw => {
return sw
})
} handleError (err, contextMessage) {
if (!err) {
console.error(contextMessage)
this.emit('error', contextMessage)
} else {
console.error(err)
this.emit('error', err)
}
}
}

sw-stream/lib/sw-stream.js

const PortStream = require('./message-channel-port-stream')

module.exports = SericeWorkerStream

function SericeWorkerStream({ serviceWorker, context }) {
// create message channel for communication
const messageChannel = new MessageChannel()
// send handshake including port to respond on
serviceWorker.postMessage({ action: 'handshake', context }, [messageChannel.port2])
// construct stream around local message channel port
const portStream = new PortStream(messageChannel.port1)
return portStream
}

最新文章

  1. kail linux 虚拟机安装实录(一) 新建虚拟机
  2. devexpress xaf 开发中遇到的问题.
  3. 武汉科技大学ACM :1007: A+B for Input-Output Practice (VII)
  4. cf B. Sereja and Suffixes
  5. Python闭包及装饰器
  6. 对象和XML文件的转换
  7. golang slice 经典例题
  8. hibernate 调用存储过程返回参数
  9. Android 开发 RecyclerView设置间距
  10. Spring_AOP 实现原理与 CGLIB 应用
  11. Protobuf3 语法指南
  12. 调试WebApi的一些方法
  13. 物联网架构成长之路(30)-Spring Boot Admin微服务WebUI监控
  14. IDEA上传码云报错Push rejected: Push to origin/master was rejected
  15. Junit + String/Integer/ArrayList/HashMap/TreeMap 基本使用Demo
  16. 《HTTP 权威指南》笔记:第三章 HTTP 报文
  17. 如何对xilinx FPGA进行bit文件加密
  18. 怎样在js中使用EL表达式
  19. 云端办公是 Office系统的未来方向么 ?
  20. Windows环境下JDK的配置及多版本JDK切换的方法记录

热门文章

  1. 【高并发解决方案】7、一致性hash解读
  2. LintCode Sqrt(x)
  3. polyfill-eventsource added missing EventSource to window ie浏览器 解决方案
  4. Python 类的特殊成员介绍
  5. python爬虫入门---第四篇:网站对爬虫的限制及突破测试
  6. 获取url参数的方法(web)
  7. Docker简单使用
  8. Django ModelForm 小实例1
  9. Python:GUI之tkinter学习笔记1控件的介绍及使用
  10. python第四十九天--paramiko模块安装大作战