手写Promise

79 阅读6分钟

手写Promise

手写Promise结构的设计

// 记录当前的三种状态
const PROMISE_PENDING = 'pending'
const PROMISE_FULFILLED = 'fulfilled'
const PROMISE_REJECTED = 'rejected'

/**
 * 注意: 
 * 1.先执行then方法.(main script)
 * 2.后执行微任务queueMicrotask()
 */
class FhPromise {
  constructor(executor) {
    this.status = PROMISE_PENDING // 默认状态
    this.value = undefined
    this.reason = undefined

    const resolve = (value) => {
      if(this.status === PROMISE_PENDING) {
        queueMicrotask(() => {

          console.log('resolve的queue');
          this.status = PROMISE_FULFILLED
          this.value = value
          this.onfulfilled(this.value)
        });
      }
    }
    const reject = (reason) => {
      if(this.status === PROMISE_PENDING) {
        queueMicrotask(() => {
          console.log('reject的queue');
          this.status = PROMISE_REJECTED
          this.reason = reason
          this.onrejected(this.reason)
        })
      }
    }
    executor(resolve, reject) // 直接执行
  }

  then(onfulfilled, onrejected) {
    console.log('then方法');
    this.onfulfilled = onfulfilled
    this.onrejected = onrejected
  }
}

const promise = new FhPromise((resolve, reject) => {
  resolve(111)
  // reject(222)
})

// 调用then方法
promise.then(res => {
  console.log('res1:', res);
},err => {
  console.log('err1', err);
})
promise.then(res => {
  console.log('res2:', res);
},err => {
  console.log('err2', err);
})

// 缺点:不允许调用多次,只拿到最后一次的执行结果.

手写Promise~then优化一

const PROMISE_PENDING = 'pending'
const PROMISE_FULFILLED = 'fulfilled'
const PROMISE_REJECTED = 'rejected'

class FhPromise {
  constructor(executor) {
    this.status = PROMISE_PENDING // 默认状态
    this.value = undefined
    this.reason = undefined
    // 保存then的回调
    this.onfulfilledFns = []
    this.onrejectedFns = []

    const resolve = (value) => {
      if(this.status === PROMISE_PENDING) {
        queueMicrotask(() => {
          if(this.status !== PROMISE_PENDING) return
          console.log('resolve的queue');
          this.status = PROMISE_FULFILLED
          this.value = value
          this.onfulfilledFns.forEach(fn => {
            fn(this.value)
          })
        });
      }
    }
    const reject = (reason) => {
      if(this.status === PROMISE_PENDING) {
        queueMicrotask(() => {
          if(this.status !== PROMISE_PENDING) return
          console.log('reject的queue');
          this.status = PROMISE_REJECTED
          this.reason = reason
          this.onrejectedFns.forEach(fn => {
            fn(this.reason)
          })
        })
      }
    }
    executor(resolve, reject)
  }

  then(onfulfilled, onrejected) {
    console.log('then方法');
    if(this.status === PROMISE_FULFILLED && onfulfilled) {
      onfulfilled(this.value)
    }
    if(this.status === PROMISE_REJECTED && onrejected) {
      onrejected(this.reason)
    }

    // 将成功回调和失败回调放在数组中(多次调用then)
    if(this.status === PROMISE_PENDING) {
      console.log('-----------------');
      this.onfulfilledFns.push(onfulfilled)

      this.onrejectedFns.push(onrejected)
    }
  }
}

const promise = new FhPromise((resolve, reject) => {
  resolve(111)
  // reject(222)
})

// 调用then方法
promise.then(res => {
  console.log('res1:', res);
},err => {
  console.log('err1:', err);
})
promise.then(res => {
  console.log('res2:', res);
},err => {
  console.log('err2:', err);
})

setTimeout(() => {
  promise.then(res => {
    console.log('res3:', res);
  }, err => {
    console.log('err3:', err);
  })
}, 1000);

手写Promise~then优化二

const PROMISE_PENDING = 'pending'
const PROMISE_FULFILLED = 'fulfilled'
const PROMISE_REJECTED = 'rejected'

// 封装工具函数
function execFnWithCatchError(execFn, value, resolve, reject) {
  try {
    const result = execFn(value)
    if(result === 'undefined') return
    console.log('xxxxxx', result);
    resolve(result)
  } catch (error) {
    reject(error)
  }
}

class FhPromise {
  constructor(executor) {
    this.status = PROMISE_PENDING // 默认状态
    this.value = undefined
    this.reason = undefined
    this.onfulfilledFns = []
    this.onrejectedFns = []

    const resolve = (value) => {
      if(this.status === PROMISE_PENDING) {
        // 添加队列微任务, 不会立即执行,主线程代码执行完,才会执行
        queueMicrotask(() => {
          if(this.status !== PROMISE_PENDING) return // 第二次进来, 是新建的FhPromise
          console.log('resolve的queue');
          this.status = PROMISE_FULFILLED
          this.value = value
          this.onfulfilledFns.forEach(fn => { //这个执行形成递归
            fn()
            console.log('```````````````````````');
          })
        });
      }
    }
    const reject = (reason) => {
      if(this.status === PROMISE_PENDING) {
        queueMicrotask(() => {
          if(this.status !== PROMISE_PENDING) return
          this.status = PROMISE_REJECTED
          this.reason = reason
          this.onrejectedFns.forEach(fn => {
            fn()
          })
        })
      }
    }
    
    try {
      executor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }

  then(onfulfilled, onrejected) {
    console.log('then方法');
    return new FhPromise((resolve, reject) => {
      if(this.status === PROMISE_FULFILLED && onfulfilled) {
        // try {
        //   const value = onfulfilled(this.value)
        //   resolve(value)
        // } catch (error) {
        //   reject(error)
        // }
        execFnWithCatchError(onfulfilled, this.value, resolve, reject)
      }
      if(this.status === PROMISE_REJECTED && onrejected) {
        // try {
        //   const reason = onrejected(this.reason)
        //   resolve(reason)
        // } catch (error) {
        //   reject(error)
        // }
        execFnWithCatchError(onrejected, this.reason, resolve, reject)
      }
  
      // 将成功回调和失败回调放在数组中(多次调用then)
      if(this.status === PROMISE_PENDING) {
        console.log('----------------');
        this.onfulfilledFns.push(() => {
          // try {
          //   const value = onfulfilled(this.value)
          //   resolve(value)
          // } catch (error) {
          //   reject(error)
          // }
          execFnWithCatchError(onfulfilled, this.value, resolve, reject)
        })
        this.onrejectedFns.push(() => {
          // try {
          //   const reason = onrejected(this.reason)
          //   resolve(reason)
          // } catch (error) {
          //   reject(error)
          // }
          execFnWithCatchError(onrejected, this.reason, resolve, reject)
        }) 
      }
    })
  }
}

const promise = new FhPromise((resolve, reject) => {
  resolve(111)
  // reject(222)
  // throw '我的err'
})

// 解决链式调用
// 调用then方法
promise.then(res => {
  console.log('res1:', res);
  return 'aaa'
  // throw '错误!'
},err => {
  console.log('err1:', err);
  return 'bbb'
}).then(res => {
  console.log('res2:', res);
}, err => {
  console.log('err2:', err);
})

手写Promise~catch方法设计

const PROMISE_PENDING = 'pending'
const PROMISE_FULFILLED = 'fulfilled'
const PROMISE_REJECTED = 'rejected'

// 封装工具函数
function execFnWithCatchError(execFn, value, resolve, reject) {
  try {
    const result = execFn(value)
    if(result === 'undefined') return
    resolve(result)
  } catch (error) {
    reject(error)
  }
}

class FhPromise {
  constructor(executor) {
    this.status = PROMISE_PENDING // 默认状态
    this.value = undefined
    this.reason = undefined
    this.onfulfilledFns = []
    this.onrejectedFns = []

    const resolve = (value) => {
      if(this.status === PROMISE_PENDING) {
        // 添加队列微任务, 不会立即执行,主线程代码执行完,才会执行
        queueMicrotask(() => {
          if(this.status !== PROMISE_PENDING) return
          this.status = PROMISE_FULFILLED
          this.value = value
          this.onfulfilledFns.forEach(fn => {
            fn()
          })
        });
      }
    }
    const reject = (reason) => {
      if(this.status === PROMISE_PENDING) {
        queueMicrotask(() => {
          if(this.status !== PROMISE_PENDING) return
          this.status = PROMISE_REJECTED
          this.reason = reason
          this.onrejectedFns.forEach(fn => {
            fn()
          })
        })
      }
    }
    
    try {
      executor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }

  then(onfulfilled, onrejected) {
    function defaultOnRejected(err) { throw err }
    onrejected = onrejected || defaultOnRejected
    // 链式调用,每次新建.所以 this.onfulfilledFns 每次只有一个
    return new FhPromise((resolve, reject) => {
      if(this.status === PROMISE_FULFILLED && onfulfilled) {
        // try {
        //   const value = onfulfilled(this.value)
        //   resolve(value)
        // } catch (error) {
        //   reject(error)
        // }
        execFnWithCatchError(onfulfilled, this.value, resolve, reject)
      }
      if(this.status === PROMISE_REJECTED && onrejected) {
        execFnWithCatchError(onrejected, this.reason, resolve, reject)
      }
      if(this.status === PROMISE_PENDING) {
        if(onfulfilled) this.onfulfilledFns.push(() => {
          execFnWithCatchError(onfulfilled, this.value, resolve, reject)
        })
        if(onrejected) {
          this.onrejectedFns.push(() => {
            execFnWithCatchError(onrejected, this.reason, resolve, reject)
          })
        }
      }
    })
  }

  catch(onrejected) {
    this.then(undefined, onrejected)
  }
}

const promise = new FhPromise((resolve, reject) => {
  // resolve(111)
  reject(222)
  // throw '我的err'
})

promise.then(res => {
  console.log('res1:', res);
}).catch(err => {
  console.log('err2', err);
})

手写Promise~finally方法设计

const PROMISE_PENDING = 'pending'
const PROMISE_FULFILLED = 'fulfilled'
const PROMISE_REJECTED = 'rejected'

// 封装工具函数
function execFnWithCatchError(execFn, value, resolve, reject) {
  try {
    const result = execFn(value)
    if(result === 'undefined') return
    resolve(result)
  } catch (error) {
    reject(error)
  }
}

class FhPromise {
  constructor(executor) {
    this.status = PROMISE_PENDING // 默认状态
    this.value = undefined
    this.reason = undefined
    this.onfulfilledFns = []
    this.onrejectedFns = []

    const resolve = (value) => {
      if(this.status === PROMISE_PENDING) {
        // 添加队列微任务, 不会立即执行,主线程代码执行完,才会执行
        queueMicrotask(() => {
          if(this.status !== PROMISE_PENDING) return
          this.status = PROMISE_FULFILLED
          this.value = value
          this.onfulfilledFns.forEach(fn => {
            fn()
          })
        });
      }
    }
    const reject = (reason) => {
      if(this.status === PROMISE_PENDING) {
        queueMicrotask(() => {
          if(this.status !== PROMISE_PENDING) return
          this.status = PROMISE_REJECTED
          this.reason = reason
          this.onrejectedFns.forEach(fn => {
            fn()
          })
        })
      }
    }
    
    try {
      executor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }

  then(onfulfilled, onrejected) {
    function defaultOnRejected(err) { throw err }
    onrejected = onrejected || defaultOnRejected

    function defaultOnFulfilled(value) { return value }
    onfulfilled = onfulfilled || defaultOnFulfilled

    // 链式调用,每次新建.所以 this.onfulfilledFns 每次只有一个
    return new FhPromise((resolve, reject) => {
      if(this.status === PROMISE_FULFILLED && onfulfilled) {
        // try {
        //   const value = onfulfilled(this.value)
        //   if(result === 'undefined') return
        //   resolve(value)
        // } catch (error) {
        //   reject(error)
        // }
        execFnWithCatchError(onfulfilled, this.value, resolve, reject)
      }
      if(this.status === PROMISE_REJECTED && onrejected) {
        execFnWithCatchError(onrejected, this.reason, resolve, reject)
      }
      if(this.status === PROMISE_PENDING) {
        if(onfulfilled) this.onfulfilledFns.push(() => {
          execFnWithCatchError(onfulfilled, this.value, resolve, reject)
        })
        if(onrejected) this.onrejectedFns.push(() => {
          execFnWithCatchError(onrejected, this.reason, resolve, reject)
        })
        
      }
    })
  }

  catch(onrejected) {
    return this.then(undefined, onrejected)
  }

  finally(onFinally) {
    this.then(() => {
      onFinally()
    }, () => {
      onFinally()
    })
  }
}

const promise = new FhPromise((resolve, reject) => {
  resolve(111)
  // reject(222)
  // throw '我的err'
})

promise.then(res => {
  console.log('res1:', res);
  return 'aaa'
}).catch(err => {
  console.log('err2', err);
}).finally(() => {
  console.log('finally');
})

手写Promiseresolvereject(类方法)

const PROMISE_PENDING = 'pending'
const PROMISE_FULFILLED = 'fulfilled'
const PROMISE_REJECTED = 'rejected'

// 封装工具函数
function execFnWithCatchError(execFn, value, resolve, reject) {
  try {
    const result = execFn(value)
    if(result === 'undefined') return
    resolve(result)
  } catch (error) {
    reject(error)
  }
}

class FhPromise {
  constructor(executor) {
    this.status = PROMISE_PENDING // 默认状态
    this.value = undefined
    this.reason = undefined
    this.onfulfilledFns = []
    this.onrejectedFns = []

    const resolve = (value) => {
      if(this.status === PROMISE_PENDING) {
        // 添加队列微任务, 不会立即执行,主线程代码执行完,才会执行
        queueMicrotask(() => {
          if(this.status !== PROMISE_PENDING) return
          this.status = PROMISE_FULFILLED
          this.value = value
          this.onfulfilledFns.forEach(fn => {
            fn()
          })
        });
      }
    }
    const reject = (reason) => {
      if(this.status === PROMISE_PENDING) {
        queueMicrotask(() => {
          if(this.status !== PROMISE_PENDING) return
          this.status = PROMISE_REJECTED
          this.reason = reason
          this.onrejectedFns.forEach(fn => {
            fn()
          })
        })
      }
    }
    
    try {
      executor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }

  then(onfulfilled, onrejected) {
    function defaultOnRejected(err) { throw err }
    onrejected = onrejected || defaultOnRejected

    function defaultOnFulfilled(value) { return value }
    onfulfilled = onfulfilled || defaultOnFulfilled

    // 链式调用,每次新建.所以 this.onfulfilledFns 每次只有一个
    return new FhPromise((resolve, reject) => {
      if(this.status === PROMISE_FULFILLED && onfulfilled) {
        execFnWithCatchError(onfulfilled, this.value, resolve, reject)
      }
      if(this.status === PROMISE_REJECTED && onrejected) {
        execFnWithCatchError(onrejected, this.reason, resolve, reject)
      }
      if(this.status === PROMISE_PENDING) {
        if(onfulfilled) this.onfulfilledFns.push(() => {
          execFnWithCatchError(onfulfilled, this.value, resolve, reject)
        })
        if(onrejected) this.onrejectedFns.push(() => {
          execFnWithCatchError(onrejected, this.reason, resolve, reject)
        })
        
      }
    })
  }

  catch(onrejected) {
    return this.then(undefined, onrejected)
  }

  finally(onFinally) {
    this.then(() => {
      onFinally()
    }, () => {
      onFinally()
    })
  }

  static resolve(value) {
    return new FhPromise(resolve => {
      resolve(value)
    })
  }

  static reject(reason) {
    return new FhPromise((resolve, reject) => {
      reject(reason)
    })
  }

}

FhPromise.resolve('123').then(res => {
  console.log('res1:', res);
})

FhPromise.reject('err mess').catch(err => {
  console.log(err);
})

手写PromiseallallSettled

const PROMISE_PENDING = 'pending'
const PROMISE_FULFILLED = 'fulfilled'
const PROMISE_REJECTED = 'rejected'

// 封装工具函数
function execFnWithCatchError(execFn, value, resolve, reject) {
  try {
    const result = execFn(value)
    if(result === 'undefined') return
    resolve(result)
  } catch (error) {
    reject(error)
  }
}

class FhPromise {
  constructor(executor) {
    this.status = PROMISE_PENDING // 默认状态
    this.value = undefined
    this.reason = undefined
    this.onfulfilledFns = []
    this.onrejectedFns = []

    const resolve = (value) => {
      if(this.status === PROMISE_PENDING) {
        // 添加队列微任务, 不会立即执行,主线程代码执行完,才会执行
        queueMicrotask(() => {
          if(this.status !== PROMISE_PENDING) return
          this.status = PROMISE_FULFILLED
          this.value = value
          this.onfulfilledFns.forEach(fn => {
            fn()
          })
        });
      }
    }
    const reject = (reason) => {
      if(this.status === PROMISE_PENDING) {
        queueMicrotask(() => {
          if(this.status !== PROMISE_PENDING) return
          this.status = PROMISE_REJECTED
          this.reason = reason
          this.onrejectedFns.forEach(fn => {
            fn()
          })
        })
      }
    }
    
    try {
      executor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }

  then(onfulfilled, onrejected) {
    function defaultOnRejected(err) { throw err }
    onrejected = onrejected || defaultOnRejected

    function defaultOnFulfilled(value) { return value }
    onfulfilled = onfulfilled || defaultOnFulfilled

    // 链式调用,每次新建.所以 this.onfulfilledFns 每次只有一个
    return new FhPromise((resolve, reject) => {
      if(this.status === PROMISE_FULFILLED && onfulfilled) {
        execFnWithCatchError(onfulfilled, this.value, resolve, reject)
      }
      if(this.status === PROMISE_REJECTED && onrejected) {
        execFnWithCatchError(onrejected, this.reason, resolve, reject)
      }
      if(this.status === PROMISE_PENDING) {
        if(onfulfilled) this.onfulfilledFns.push(() => {
          execFnWithCatchError(onfulfilled, this.value, resolve, reject)
        })
        if(onrejected) this.onrejectedFns.push(() => {
          execFnWithCatchError(onrejected, this.reason, resolve, reject)
        })
        
      }
    })
  }

  catch(onrejected) {
    return this.then(undefined, onrejected)
  }

  finally(onFinally) {
    this.then(() => {
      onFinally()
    }, () => {
      onFinally()
    })
  }

  static resolve(value) {
    return new FhPromise(resolve => {
      resolve(value)
    })
  }

  static reject(reason) {
    return new FhPromise((resolve, reject) => {
      reject(reason)
    })
  }

  static all(promises) {
    return new FhPromise((resolve, reject) => {
      let values = []
      promises.forEach((promise) => {
        promise.then(res => {
          values.push(res)
          if(values.length === promises.length){
            resolve(values)
          }
        }, err => {
          reject(err)
        })
      })
    })
  }

  static allSettled(promises) {
    return new FhPromise((resolve) => {
      let results = []
      promises.forEach(promise => {
        promise.then(res => {
          results.push({ status: PROMISE_FULFILLED, value: res })
          if(results.length === promises.length){
            resolve(results)
          }
        }, err => {
          results.push({ status: PROMISE_REJECTED, value: err })
          if(results.length === promises.length){
            resolve(results)
          }
        })
      })
    })
  }
}

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => { resolve(11111) }, 1000);
})
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => { resolve(22222) }, 2000);
  // setTimeout(() => { reject('error!') }, 2000);
})
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => { resolve(33333) }, 3000);
})

// FhPromise.all([p1, p2, p3]).then( res =>{
//   console.log(res);
// }).catch(err => {
//   console.log(err);
// })

FhPromise.allSettled([p1, p2, p3]).then( res =>{
  console.log(res);
})

手写Promiseraceany

const PROMISE_PENDING = 'pending'
const PROMISE_FULFILLED = 'fulfilled'
const PROMISE_REJECTED = 'rejected'

// 封装工具函数
function execFnWithCatchError(execFn, value, resolve, reject) {
  try {
    const result = execFn(value)
    if(result === 'undefined') return
    resolve(result)
  } catch (error) {
    reject(error)
  }
}

class FhPromise {
  constructor(executor) {
    this.status = PROMISE_PENDING // 默认状态
    this.value = undefined
    this.reason = undefined
    this.onfulfilledFns = []
    this.onrejectedFns = []

    const resolve = (value) => {
      if(this.status === PROMISE_PENDING) {
        // 添加队列微任务, 不会立即执行,主线程代码执行完,才会执行
        queueMicrotask(() => {
          if(this.status !== PROMISE_PENDING) return
          this.status = PROMISE_FULFILLED
          this.value = value
          this.onfulfilledFns.forEach(fn => {
            fn()
          })
        });
      }
    }
    const reject = (reason) => {
      if(this.status === PROMISE_PENDING) {
        queueMicrotask(() => {
          if(this.status !== PROMISE_PENDING) return
          this.status = PROMISE_REJECTED
          this.reason = reason
          this.onrejectedFns.forEach(fn => {
            fn()
          })
        })
      }
    }
    
    try {
      executor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }

  then(onfulfilled, onrejected) {
    function defaultOnRejected(err) { throw err }
    onrejected = onrejected || defaultOnRejected

    function defaultOnFulfilled(value) { return value }
    onfulfilled = onfulfilled || defaultOnFulfilled

    // 链式调用,每次新建.所以 this.onfulfilledFns 每次只有一个
    return new FhPromise((resolve, reject) => {
      if(this.status === PROMISE_FULFILLED && onfulfilled) {
        execFnWithCatchError(onfulfilled, this.value, resolve, reject)
      }
      if(this.status === PROMISE_REJECTED && onrejected) {
        execFnWithCatchError(onrejected, this.reason, resolve, reject)
      }
      if(this.status === PROMISE_PENDING) {
        if(onfulfilled) this.onfulfilledFns.push(() => {
          execFnWithCatchError(onfulfilled, this.value, resolve, reject)
        })
        if(onrejected) this.onrejectedFns.push(() => {
          execFnWithCatchError(onrejected, this.reason, resolve, reject)
        })
        
      }
    })
  }

  catch(onrejected) {
    return this.then(undefined, onrejected)
  }

  finally(onFinally) {
    this.then(() => {
      onFinally()
    }, () => {
      onFinally()
    })
  }

  static resolve(value) {
    return new FhPromise(resolve => {
      resolve(value)
    })
  }

  static reject(reason) {
    return new FhPromise((resolve, reject) => {
      reject(reason)
    })
  }

  static all(promises) {
    return new FhPromise((resolve, reject) => {
      let values = []
      promises.forEach((promise) => {
        promise.then(res => {
          values.push(res)
          if(values.length === promises.length){
            resolve(values)
          }
        }, err => {
          reject(err)
        })
      })
    })
  }

  static allSettled(promises) {
    return new FhPromise((resolve) => {
      let results = []
      promises.forEach(promise => {
        promise.then(res => {
          results.push({ status: PROMISE_FULFILLED, value: res })
          if(results.length === promises.length){
            resolve(results)
          }
        }, err => {
          results.push({ status: PROMISE_REJECTED, value: err })
          if(results.length === promises.length){
            resolve(results)
          }
        })
      })
    })
  }

  static race(promises) {
    return new FhPromise((resolve, reject) => {
      promises.forEach(promise => {
        // promise.then(res => {
        //   resolve(res)
        // }, err => {
        //   reject(err)
        // })
        // promise.then(resolve, reject)
        promise.then(res => {
          resolve(res)
        }, err => {
          reject(err)
        })
      })
    })
  }

  static any(promises) {
    return new FhPromise((resolve, reject) => {
      let errs = []
      promises.forEach(promise => {
        promise.then(res => {
          resolve(res)
        }, err => {
          errs.push(err)
          if(errs.length === promises.length){
            reject(errs)
          }
        })
      })
    })
  }
}

const p1 = new Promise((resolve, reject) => {
  // setTimeout(() => { resolve(11111) }, 1000);
  setTimeout(() => { reject('error1') }, 1000);
})
const p2 = new Promise((resolve, reject) => {
  // setTimeout(() => { resolve(22222) }, 2000);
  setTimeout(() => { reject('error2') }, 2000);
})
const p3 = new Promise((resolve, reject) => {
  // setTimeout(() => { resolve(33333) }, 3000);
  setTimeout(() => { reject('error3') }, 3000);
})

// FhPromise.race([p1, p2, p3]).then(res => {
//   console.log('res:', res);
// }).catch(err => {
//   console.log('err:', err);
// })

FhPromise.any([p1, p2, p3]).then(res => {
  console.log('res:', res);
}).catch(err => {
  console.log('err:', err);
})