| 'use strict'; |
| const pTimeout = require('p-timeout'); |
| |
| module.exports = (emitter, event, opts) => { |
| let cancel; |
| |
| const ret = new Promise((resolve, reject) => { |
| if (typeof opts === 'function') { |
| opts = {filter: opts}; |
| } |
| |
| opts = Object.assign({ |
| rejectionEvents: ['error'], |
| multiArgs: false |
| }, opts); |
| |
| let addListener = emitter.on || emitter.addListener || emitter.addEventListener; |
| let removeListener = emitter.off || emitter.removeListener || emitter.removeEventListener; |
| |
| if (!addListener || !removeListener) { |
| throw new TypeError('Emitter is not compatible'); |
| } |
| |
| addListener = addListener.bind(emitter); |
| removeListener = removeListener.bind(emitter); |
| |
| const resolveHandler = function (value) { |
| if (opts.multiArgs) { |
| value = [].slice.apply(arguments); |
| } |
| |
| if (opts.filter && !opts.filter(value)) { |
| return; |
| } |
| |
| cancel(); |
| resolve(value); |
| }; |
| |
| const rejectHandler = function (reason) { |
| cancel(); |
| |
| if (opts.multiArgs) { |
| reject([].slice.apply(arguments)); |
| } else { |
| reject(reason); |
| } |
| }; |
| |
| cancel = () => { |
| removeListener(event, resolveHandler); |
| |
| for (const rejectionEvent of opts.rejectionEvents) { |
| removeListener(rejectionEvent, rejectHandler); |
| } |
| }; |
| |
| addListener(event, resolveHandler); |
| |
| for (const rejectionEvent of opts.rejectionEvents) { |
| addListener(rejectionEvent, rejectHandler); |
| } |
| }); |
| |
| ret.cancel = cancel; |
| |
| if (typeof opts.timeout === 'number') { |
| return pTimeout(ret, opts.timeout); |
| } |
| |
| return ret; |
| }; |