美文网首页
如何实现一个 promisify ?

如何实现一个 promisify ?

作者: 人话博客 | 来源:发表于2022-01-21 16:13 被阅读0次

    早期的异步函数,由于还没有 Promise,所以都是以回调的方式来处理异步任务的.

    function someAsyncTask (num, cb) {
      setTimeout(() => {
        const result = num * 100
        typeof cb === 'function' && cb(result)
      }, 2000);
    }
    
    someAsyncTask(100, (result) => {
      console.log('回调异步处理的结果是:' + result)
    })
    

    目标和希望

    function promisify (asyncFn) {
        // 如果实现一个逻辑,将 asyncFn 转换成一个 Promise 对象返回?
        return  new Promise () //....
    }
    
    const promiseInstance = promisify(someAsyncTask)
    
    promiseInstance.then(data=>{
        console.log('在这里拿到异步返回的数据 data')
    })
    
    

    如何实现?

    核心思想: 你要是能用 Promiseresovle 函数替代原异步函数的 cb 函数即可.

    function someAsyncTask (num, cb) {
      setTimeout(() => {
        const result = num * 100
        typeof cb === 'function' && cb(result)
      }, 2000);
    }
    
    // 接受一个异步任务函数(非 promise)
    // 返回一个 promise 对象
    function promisify (asyncTask) {
      return (...args) => {
        return new Promise((resolve, reject) => {
          // 用你的 resolve 去覆盖别人本身的 cb 即可.
          asyncTask.apply(null, [...args, resolve])
        })
      }
    }
    
    const p = promisify(someAsyncTask)
    p(100).then(res => {
      console.log(res);
    })
    

    2s 后输出 10000

    结果

    完善一下这个例子.

    上述例子,仅支持 Promise 的成功回调. 但是对于失败的 reject 却无法处理.

    解决办法:

    callback 具体指向 resolve 还是 reject 由当前的异步函数自己决定

    function promisify (asyncTask) {
      return (...args) => {
        return new Promise((resolve, reject) => {
          // 让用户自己决定调用 resolve 还是 reject
          let callback = (err) => {
            return err ? resolve : reject
          }
          asyncTask.apply(null, [...args, callback])
        })
    }
    
    

    注意: promisify 函数有一个局限. 被包装的异步函数,回调函数必须是最后一个参数!

    相关文章

      网友评论

          本文标题:如何实现一个 promisify ?

          本文链接:https://www.haomeiwen.com/subject/aapshrtx.html