从头开始的 Javascript Promise

标签 javascript promise

我从头开始编写基本 Promise 时遇到错误,并且不知道为什么 this.status 会产生错误

class Promisify {
  constructor(fn) {
    this.status = 0; // 0 = unfulfilled, 1 = resolved, 2 = rejected
    this.result = undefined;
    this.error = undefined;
    this.thenFns = [];
    this.catchFns = [];
    this.finallyFn = undefined;

    try {
      fn(this._resolve, this._reject);
    } catch (e) {
      this._reject(e);
    }
  }


  // public methods
  then(fn) {
    this.thenFns.push(fn);
    this._doThen();
    return this;
  }

  catch(fn) {
    this.catchFns.push(fn);
    this._doCatch();
    return this;
  };
  
  finally(fn) {
    this.finallyFn = fn;
    return this;
  }

  // private methods
  _doThen() {
    if (this.status === 1) {
      while(this.thenFns.length) {
        this.thenFns.shift()(this.result);
      }
    }
  }

  _doCatch() {
    if (this.status === 2) {
      if (this.catchFns.length === 0) {
        console.error('uncaught error')
      }
      while(this.catchFns.length) {
        this.catchFns.shift()(this.error);
      }
    }
  }

  _resolve(r) {
    if(this.status) 
      throw Error('cannot resolve, already handled');
    this.status = 1;
    this.result = r;
    this._doThen();
  }
  
  _reject(e) {
    if (this.status) throw Error('cannot reject, already handled');
    this.status = 2;
    this.error = e;
    this._doCatch();
  }
}

最佳答案

如果你想将你的函数传递给其他人调用

 fn(this._resolve, this._reject);

并且在调用时让 this 指向您的 Promise 对象,您需要显式绑定(bind)它们:

  fn(this._resolve.bind(this), this._reject.bind(this));

class Promisify {
   constructor(fn) {
     this.status = 0; // 0 = unfulfilled, 1 = resolved, 2 = rejected
     this.result = undefined;
     this.error = undefined;
     this.thenFns = [];
     this.catchFns = [];
     this.finallyFn = undefined;
 
     try {
       fn(this._resolve.bind(this), this._reject.bind(this));
     } catch (e) {
       this._reject(e);
     }
   }
 
   // public methods
   then(fn) {
     this.thenFns.push(fn);
     this._doThen();
     return this;
   }
 
   catch(fn) {
     this.catchFns.push(fn);
     this._doCatch();
     return this;
   };
   
   finally(fn) {
     this.finallyFn = fn;
     return this;
   }
 
   // private methods
   _doThen() {
     if (this.status === 1) {
       while(this.thenFns.length) {
         this.thenFns.shift()(this.result);
       }
     }
   }
 
   _doCatch() {
     if (this.status === 2) {
       if (this.catchFns.length === 0) {
         console.error('uncaught error')
       }
       while(this.catchFns.length) {
         this.catchFns.shift()(this.error);
       }
     }
   }
 
   _resolve(r) {
     if(this.status) 
       throw Error('cannot resolve, already handled');
     this.status = 1;
     this.result = r;
     this._doThen();
   }
   
   _reject(e) {
     if (this.status) throw Error('cannot reject, already handled');
     this.status = 2;
     this.error = e;
     this._doCatch();
   }
 }
 

 const demo = new Promisify((resolve, reject) => {
   setTimeout(function() {
     resolve('Howdy!')
   }, 1000);
 });
 
 demo
.then(val => console.log("Demo Value in Then!!", val))
.catch(console.error) //Should throw an error.
.then(val => console.log("Second then!"))
.catch((err) => {
    throw new Error('error', err);
})
.finally(val => console.log("Executed Finally"))
 

关于从头开始的 Javascript Promise,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60292264/

相关文章:

javascript - 问卷的正确数据结构是什么

node.js - Node Promise 如何进入 `nextTick` 和 `setImmediate` 之间?

node.js - 如何创建文件流并异步写入流?

javascript - 使用 Promises 在 for 循环中调用 API 的最佳方法

javascript - 如何向 Draft js 编辑器添加可点击的填充

javascript - 如何使用 NodeJS Express 服务器在 HTML 中包含 JS 文件?

javascript - addEventListener 无法正常工作

javascript - 在映射下一项之前,异步等待映射不等待异步函数在映射函数内部完成

javascript - 处理多个 React 组件之间的 Promise

javascript - 重启 css 过渡