为了账号安全,请及时绑定邮箱和手机立即绑定

从头开始创建的自定义 JavaScript Promise 中的“然后”会在 Promise

从头开始创建的自定义 JavaScript Promise 中的“然后”会在 Promise

缥缈止盈 2023-10-14 11:18:00
我正在尝试从头开始创建一个简单的自定义承诺。由于某种原因,在调用then之前正在执行。onResolve function因此,该response变量是一个空字符串。我这里哪里出错了?索引.jsimport CustomPromise from "./customPromise";const makeApiCall = () => {  return new CustomPromise((success, failure) => {    setTimeout(() => {      let apiResponse = { statusCode: 200, response: "hello" };      if (apiResponse.statusCode == 200) {        success(apiResponse);      } else {        failure(apiResponse);      }    }, 1000);  });};makeApiCall().then(response => {  console.log(response);});CustomPromise.jsexport default class CustomPromise {  constructor(executorFunc) {    this.onResolve = this.onResolve.bind(this);    this.onReject = this.onReject.bind(this);    this.response = "";    executorFunc(this.onResolve, this.onReject);  }  then(input) {    input(this.response);  }  onResolve(response) {    this.response = response;  }  onReject(input) {    input();  }}
查看完整描述

1 回答

?
SMILET

TA贡献1796条经验 获得超4个赞

当调用时,CustomPromise.then您可以看到您只是在继续input并立即调用它,而不管承诺的状态如何。我认为您想要做的是创建一个task queue,并在解决后,您将继续执行它。

您还错过了一些关键的事情。

  1. 首先,您需要维护一个state内部的 Promise,以便您知道 Promise 何时发生settled。这使得您无法多次解决/拒绝承诺。

  2. 您的reject函数可能不应该只是执行输入。您通常将 a 传递reason给拒绝,然后它将执行所有catch任务。

  3. 没有链接支持。不确定这是否是你的目标。

const functionOrNoop = (fn) => {

  let result = () => {};


  if (typeof fn === "function") {

    result = fn;

  }


  return result;

};


class CustomPromise {

  constructor(executor) {

    this.queue = [];

    this.state = "pending";

    this.value = null;

    this.reason = null;


    executor(this.onResolve, this.onReject);

  }


  static reject(reason) {

    return new CustomPromise((_, reject) => reject(reason));

  }


  static resolve(value) {

    return new CustomPromise((resolve) => resolve(value));

  }


  then(fn) {

    return new CustomPromise((resolve, reject) => {

      const resolved = (value) => {

        try {

          resolve(fn(value))

        } catch (e) {

          reject(e);

        }

      };


      this.enqueue({

        resolved,

        rejected: reject

      });

    });

  }


  catch (fn) {

    return new CustomPromise((resolve, reject) => {

      const rejected = (reason) => {

        try {

          resolve(fn(reason))

        } catch (e) {

          reject(e);

        }

      };


      this.enqueue({

        rejected

      });

    });

  }


  onResolve = (value) => {

    if (this.state === "pending") {

      this.state = "resolved";

      this.value = value;

      this.finalize();

    }

  }


  onReject = (reason) => {

    if (this.state === "pending") {

      this.state = "rejected";

      this.reason = reason;

      this.finalize();

    }

  };


  enqueue(task) {

    if (this.state === "pending") {

      this.queue.push(task);

    } else {

      this.eval(task);

    }

  }


  eval(task) {

    if (this.state === "resolved") {

      functionOrNoop(task.resolved)(this.value);

    } else if (this.state === "rejected") {

      functionOrNoop(task.rejected)(this.reason);

    }

  }


  finalize() {

    this.queue.forEach((task) => this.eval(task));

    this.queue = [];

  }

}


const p = CustomPromise.resolve("hello")


p

  .then((value) => value.toUpperCase())

  .then((value) => `J${value.slice(1)}`)

  .then((value) => console.log(value))


p.then((value) => console.log(value));


p

  .then(() => {

    throw new Error(":(")

  })

  .catch((e) => console.log(e.message))

  .then(() => {

    throw new Error(":)")

  })

  .then(() => console.log("SHOULD NOT CALL!"))

  .catch((e) => console.log(e.message));


这是一个示例(所以预计会有错误),但它封装了我上面提到的一些内容。Promise 确实很复杂,您会错过诸如“微任务”之类的东西以及数万小时的测试、开发和审查。


查看完整回答
反对 回复 2023-10-14
  • 1 回答
  • 0 关注
  • 61 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信