zoukankan      html  css  js  c++  java
  • sw-stream

    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 * 2
        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[0]
          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: 42 })
        })
        .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
    }





  • 相关阅读:
    宝藏 题解
    Xorequ 题解
    2020.12.26 模拟赛 题解
    数据结构 100 题 1~10 线段树
    关于模拟退火
    诗意狗 题解
    Keyboading 思路
    体育成绩统计/ Score
    【(抄的)题解】P5686 [CSP-SJX2019]和积和
    【笔记】简单博弈
  • 原文地址:https://www.cnblogs.com/wanghui-garcia/p/9915565.html
Copyright © 2011-2022 走看看