import { is } from './is' ; type Next = ( data : any ) => any ; interface IConfig { before ? : ( data : any ) => any ; after ? : ( data : any ) => any ; } export class Queue { private before : ( data : any ) => any ; private after : ( data : any ) => any ; private end : Next ; private isFirst : boolean = true ; private queue : ( ( next : Next , data : any ) => void ) [ ] = [ ] ; constructor ( config ? ) { const { before = data => data , after = data => data } = config || { } ; this . before = before ; this . after = after ; } public push ( fn ) { if ( is . fn ( fn ) ) this . queue . push ( fn ) ; } public perform ( end , initData ? ) { this . end = end ; this . _next ( initData ) ; } private _next = ( data ) => { if ( ! this . isFirst ) data = this . after ( data ) ; if ( this . queue . length > 0 ) { const fn = this . queue . shift ( ) ; if ( fn ) { data = this . before ( data ) ; fn ( this . _next , data ) ; this . isFirst = false ; } } else { this . end ( data ) ; this . queue = [ ] ; } } ; } export class MQueue { private _queue : Queue ; constructor ( ) { this . _queue = new Queue ( ) ; } public line ( fn ) { this . _queue . push ( ( next , data ) => { setTimeout ( async ( ) => { const nextData = fn ( data ) ; if ( is . promise ( nextData ) ) { nextData . then ( next ) ; } else { next ( nextData ) ; } } , 0 ) ; } ) ; return this ; } public start ( end , initData ? ) { this . _queue . perform ( end , initData ) ; } }