首页 > 解决方案 > Promise 的一个极其简单的实现是如何工作的

问题描述

我正在阅读这篇关于promise. 为此,作者展示了一个promise正常工作的简化实现。

代码如下:

class PromiseSimple {
  constructor(executionFunction) {
    this.promiseChain = [];
    this.handleError = () => {};

    this.onResolve = this.onResolve.bind(this);
    this.onReject = this.onReject.bind(this);

    executionFunction(this.onResolve, this.onReject);
  }

  then(onResolve) {
    this.promiseChain.push(onResolve);

    return this;
  }

  catch(handleError) {
    this.handleError = handleError;

    return this;
  }

  onResolve(value) {
    let storedValue = value;

    try {
      this.promiseChain.forEach((nextFunction) => {
         storedValue = nextFunction(storedValue);
      });
    } catch (error) {
      this.promiseChain = [];

      this.onReject(error);
    }
  }

  onReject(error) {
    this.handleError(error);
  }
}

它被这样称呼,就像一个普通的promise

// Assume this is your AJAX library. Almost all newer
// ones return a Promise Object
const makeApiCall = () => {
  return new PromiseSimple((resolve, reject) => {
    // Use a timeout to simulate the network delay waiting for the response.
    // This is THE reason you use a promise. It waits for the API to respond
    // and after received, it executes code in the `then()` blocks in order.
    // If it executed is immediately, there would be no data.
    setTimeout(() => {
      const apiResponse = fakeApiBackend();

      if (apiResponse.statusCode >= 400) {
        reject(apiResponse);
      } else {
        resolve(apiResponse.data);
      }
    }, 5000);
  });
};

我很难掌握以下内容:

  1. 为什么行67PromiseSimple存在?我试图理解绑定this.onResolvethis. 它不是已经绑定到适当的this上下文了吗?

  2. 我不明白为什么这个实现不会阻塞主线程。在PromiseSimple类中的任何地方都没有将工作卸载到另一个线程或任何类似的东西上。但可以肯定的是,如果我console.log(...)在程序的最后放置一个语句,该console.log(...)语句将作为我期望的第一件事被打印出来,就像一个常规的promise. 我想它会被暂停,直到假makeApiCall函数完成,因为这不是一个真正的实现promise

我想掌握这一点,但我只是不明白这个迷你实现如何允许promise我们习惯的正确行为。任何帮助是极大的赞赏。


更新

已经提出了将其复制的建议,但我想详细说明为什么它们不一样。重复的问题是关于为什么需要异步调用的更高层次的理论。我了解它们的用途、重要性以及实施它们的各种方式。我希望了解它们的工作原理。

标签: javascriptasynchronouspromise

解决方案


  1. onResolve并且onReject必须绑定以防止executionFunction将它们与另一个上下文或没有任何上下文一起应用。(如果出于任何原因您调用resolvereject使用其他上下文,它必须绑定到PromiseSimple,否则this将引用其他内容,或者如果没有上下文则不会引用任何内容)。

onResolve这是一个如果您不绑定或将不起作用的示例onReject

const makeApiCall = () => {
    return new PromiseSimple((resolve, reject) => {
        Promise.resolve().then(resolve); // Using native promise here : resolve is called without context and won't work if not bound
    });
}
  1. 这个实现确实阻塞了主线程,但你可能看不到它,因为你使用了一个 setTimeout 来延迟事件循环中的执行。真正的 Promise 实现会延迟您在事件循环中定义thencatch回调为微任务的任务。(有一篇关于浏览器事件循环的非常有趣的文章)。

希望这可以帮助,


推荐阅读