123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- 'use strict'
- const Dispatcher = require('./dispatcher')
- const {
- ClientDestroyedError,
- ClientClosedError,
- InvalidArgumentError
- } = require('./core/errors')
- const { kDestroy, kClose, kDispatch, kInterceptors } = require('./core/symbols')
- const kDestroyed = Symbol('destroyed')
- const kClosed = Symbol('closed')
- const kOnDestroyed = Symbol('onDestroyed')
- const kOnClosed = Symbol('onClosed')
- const kInterceptedDispatch = Symbol('Intercepted Dispatch')
- class DispatcherBase extends Dispatcher {
- constructor () {
- super()
- this[kDestroyed] = false
- this[kOnDestroyed] = null
- this[kClosed] = false
- this[kOnClosed] = []
- }
- get destroyed () {
- return this[kDestroyed]
- }
- get closed () {
- return this[kClosed]
- }
- get interceptors () {
- return this[kInterceptors]
- }
- set interceptors (newInterceptors) {
- if (newInterceptors) {
- for (let i = newInterceptors.length - 1; i >= 0; i--) {
- const interceptor = this[kInterceptors][i]
- if (typeof interceptor !== 'function') {
- throw new InvalidArgumentError('interceptor must be an function')
- }
- }
- }
- this[kInterceptors] = newInterceptors
- }
- close (callback) {
- if (callback === undefined) {
- return new Promise((resolve, reject) => {
- this.close((err, data) => {
- return err ? reject(err) : resolve(data)
- })
- })
- }
- if (typeof callback !== 'function') {
- throw new InvalidArgumentError('invalid callback')
- }
- if (this[kDestroyed]) {
- queueMicrotask(() => callback(new ClientDestroyedError(), null))
- return
- }
- if (this[kClosed]) {
- if (this[kOnClosed]) {
- this[kOnClosed].push(callback)
- } else {
- queueMicrotask(() => callback(null, null))
- }
- return
- }
- this[kClosed] = true
- this[kOnClosed].push(callback)
- const onClosed = () => {
- const callbacks = this[kOnClosed]
- this[kOnClosed] = null
- for (let i = 0; i < callbacks.length; i++) {
- callbacks[i](null, null)
- }
- }
- // Should not error.
- this[kClose]()
- .then(() => this.destroy())
- .then(() => {
- queueMicrotask(onClosed)
- })
- }
- destroy (err, callback) {
- if (typeof err === 'function') {
- callback = err
- err = null
- }
- if (callback === undefined) {
- return new Promise((resolve, reject) => {
- this.destroy(err, (err, data) => {
- return err ? /* istanbul ignore next: should never error */ reject(err) : resolve(data)
- })
- })
- }
- if (typeof callback !== 'function') {
- throw new InvalidArgumentError('invalid callback')
- }
- if (this[kDestroyed]) {
- if (this[kOnDestroyed]) {
- this[kOnDestroyed].push(callback)
- } else {
- queueMicrotask(() => callback(null, null))
- }
- return
- }
- if (!err) {
- err = new ClientDestroyedError()
- }
- this[kDestroyed] = true
- this[kOnDestroyed] = this[kOnDestroyed] || []
- this[kOnDestroyed].push(callback)
- const onDestroyed = () => {
- const callbacks = this[kOnDestroyed]
- this[kOnDestroyed] = null
- for (let i = 0; i < callbacks.length; i++) {
- callbacks[i](null, null)
- }
- }
- // Should not error.
- this[kDestroy](err).then(() => {
- queueMicrotask(onDestroyed)
- })
- }
- [kInterceptedDispatch] (opts, handler) {
- if (!this[kInterceptors] || this[kInterceptors].length === 0) {
- this[kInterceptedDispatch] = this[kDispatch]
- return this[kDispatch](opts, handler)
- }
- let dispatch = this[kDispatch].bind(this)
- for (let i = this[kInterceptors].length - 1; i >= 0; i--) {
- dispatch = this[kInterceptors][i](dispatch)
- }
- this[kInterceptedDispatch] = dispatch
- return dispatch(opts, handler)
- }
- dispatch (opts, handler) {
- if (!handler || typeof handler !== 'object') {
- throw new InvalidArgumentError('handler must be an object')
- }
- try {
- if (!opts || typeof opts !== 'object') {
- throw new InvalidArgumentError('opts must be an object.')
- }
- if (this[kDestroyed] || this[kOnDestroyed]) {
- throw new ClientDestroyedError()
- }
- if (this[kClosed]) {
- throw new ClientClosedError()
- }
- return this[kInterceptedDispatch](opts, handler)
- } catch (err) {
- if (typeof handler.onError !== 'function') {
- throw new InvalidArgumentError('invalid onError method')
- }
- handler.onError(err)
- return false
- }
- }
- }
- module.exports = DispatcherBase
|