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
    }





  • 相关阅读:
    hdu acm 2844 Coins 解题报告
    hdu 1963 Investment 解题报告
    codeforces 454B. Little Pony and Sort by Shift 解题报告
    广大暑假训练1 E题 Paid Roads(poj 3411) 解题报告
    hdu acm 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
    hdu acm 1114 Piggy-Bank 解题报告
    poj 2531 Network Saboteur 解题报告
    数据库范式
    ngnix 配置CI框架 与 CI的简单使用
    Vundle的安装
  • 原文地址:https://www.cnblogs.com/wanghui-garcia/p/9915565.html
Copyright © 2011-2022 走看看