• 手写Promise(一)


    参考地址:地址。

    目录

    一,搭建整体框架和添加then方法到Promise原型

    二,实现executor执行器,完善resolve和reject函数

    三,实现throw抛出异常后置PromiseState = 'no'

    四,完善PromiseState只能被修改一次

    五,实现then方法对resolved,rejected状态的支持

    六,实现then方法对pending状态的支持

    七,实现then绑定多个回调函数

    八,实现then返回一个Promise对象(由同步任务决定状态)


    一,搭建整体框架和添加then方法到Promise原型

    1. function myPromise(executor) {
    2. }
    3. myPromise.prototype.then(solved, rejectd);

    二,实现executor执行器,完善resolve和reject函数

    1. function myPromise(executor) {
    2. //令executor === (f = (resolve, reject) => resolve('ok'));用于测试的操作,省去了异步操作,resolve, reject函数选择resolve执行
    3. /*置初始状态*/
    4. this.PromiseState = 'waiting';
    5. /*置初始结果*/
    6. this.PromiseResult = null;
    7. /*让ins指向实例对象*/
    8. const ins = this;
    9. /*实现resolve函数,将异步操作的结果给PromiseResult*/
    10. function resolve(data) {
    11. /*改变实例对象的状态*/
    12. ins.PromiseState = 'yes';
    13. ins.PromiseResult = data;
    14. };
    15. /*实现reject函数*/
    16. function reject(data) {
    17. ins.PromiseState = 'no';
    18. ins.PromiseResult = data;
    19. };
    20. /*同步调用执行器,执行传进来的任务,executor被主线程执行后将异步操作放入事件队列*/
    21. executor(resolve, reject);
    22. //在这里声明resolve, reject这两个变量,根据业务逻辑选择必须resolve, reject二选一执行,将结果交给resolve, reject即可。
    23. }
    24. myPromise.prototype.then = function(onresolved, onrejectd) {
    25. };
    26. };

    三,实现throw抛出异常后置PromiseState = 'no'

            我这个例子写的是no,官方的是rejected。因为只有executor执行出了问题才会异常(貌似只有executor可以执行),所以将executor放入trycatch中。

    1. //单独的解决方法
    2. try {
    3. executor(resolve, reject);
    4. } catch (error) {
    5. reject(error);
    6. }

    四,完善PromiseState只能被修改一次

            解决方法如下:

    1. function resolve(data) {
    2. /*改变实例对象的状态*/
    3. if (ins.PromiseState == 'waiting') {
    4. ins.PromiseState = 'yes';
    5. }
    6. ins.PromiseResult = data;
    7. };
    8. /*实现reject函数*/
    9. function reject(data) {
    10. if (ins.PromiseState == 'waiting') {
    11. ins.PromiseState = 'no';
    12. }
    13. ins.PromiseResult = data;
    14. };

    五,实现then方法对resolved,rejected状态的支持

            实现方法如下。本例使用yes和no代替。

    1. myPromise.prototype.then = function(onresolved, onrejectd) {
    2. if (this.PromiseState == 'yes') {
    3. onresolved(this.PromiseResult); //将实例对象的结果传给回调函数进行处理
    4. }
    5. if (this.PromiseState == 'no') {
    6. onrejectd(this.PromiseResult);
    7. }
    8. };

    六,实现then方法对pending状态的支持

            本例以waiting为例。处于pending的状态大都是因为执行器中放了一个耗时的异步操作,一直没有调用resolve, reject这两个函数,导致状态一直为pending。

            但是then方法的作为参数的两个回调方法只能处理resolved和rejected状态。而且then方法不可能给pending状态添加回调函数,因为对pending状态进行处理会让主线程挂起,这是不可行的。

            另外,如果主线程在还是pending状态时就执行到then方法,会将then方法丢进事件队列(微任务队列),然后接着运行下面的代码,在这之后如果状态改变该如何处理需要被解决。

            解决方法就是:将resolved和rejected状态对应的回调函数进行保存,等到状态变化之后再执行。

    1. function myPromise(executor) {
    2. //令executor === (f = (resolve, reject) => resolve('ok'));用于测试的操作,省去了异步操作,resolve, reject函数选择resolve执行
    3. /*置初始状态*/
    4. this.PromiseState = 'waiting';
    5. /*置初始结果*/
    6. this.PromiseResult = null;
    7. /*让ins指向实例对象*/
    8. const ins = this;
    9. /*保存当前实例对象的两个回调函数*/
    10. ins.callback = {};
    11. /*实现resolve函数,将异步操作的结果给PromiseResult*/
    12. function resolve(data) {
    13. /*改变实例对象的状态*/
    14. if (ins.PromiseState == 'waiting') {
    15. ins.PromiseState = 'yes';
    16. }
    17. ins.PromiseResult = data;
    18. /*对是否为waiting状态进行判断,如果主线程经过then的时候还是waiting,则具有solved,rejected两个属性*/
    19. if (ins.callback.solved) {
    20. ins.callback.solved(data);
    21. }
    22. };
    23. /*实现reject函数*/
    24. function reject(data) {
    25. if (ins.PromiseState == 'waiting') {
    26. ins.PromiseState = 'no';
    27. }
    28. ins.PromiseResult = data;
    29. /*对是否为waiting状态进行判断,如果主线程经过then的时候还是waiting,则具有solved,rejected两个属性*/
    30. if (ins.callback.rejected) {
    31. ins.callback.rejected(data);
    32. }
    33. };
    34. /*同步调用执行器,执行传进来的任务,executor被主线程执行后将异步操作放入事件队列*/
    35. try {
    36. //在这里声明resolve, reject这两个变量,根据业务逻辑选择必须resolve, reject二选一执行,将结果交给resolve, reject即可。
    37. executor(resolve, reject);
    38. } catch (error) {
    39. reject(error);
    40. }
    41. }
    42. myPromise.prototype.then = function(solved, rejected) {
    43. //solved, rejected分别对应成功和失败的回调函数。
    44. if (this.PromiseState == 'yes') {
    45. solved(this.PromiseResult); //将实例对象的结果传给回调函数进行处理
    46. }
    47. if (this.PromiseState == 'no') {
    48. rejected(this.PromiseResult);
    49. }
    50. //当主线程执行到then方法的时候还是pending状态的话就将两个回调函数保存,主线程放弃了他们,程序员不能
    51. if (this.PromiseState == 'waiting') {
    52. this.callbacks = {
    53. solved,
    54. rejected
    55. }
    56. }
    57. };

    七,实现then绑定多个回调函数

            多次给then绑定不同的回调函数,会丢失对前面的联系,只会绑定到最后一次的回调函数。当多次使用:p.then时,把这些回调函数都保存起来,然后依次调用即可。

    1. function myPromise(executor) {
    2. //令executor === (f = (resolve, reject) => resolve('ok'));用于测试的操作,省去了异步操作,resolve, reject函数选择resolve执行
    3. /*置初始状态*/
    4. this.PromiseState = 'waiting';
    5. /*置初始结果*/
    6. this.PromiseResult = null;
    7. /*让ins指向实例对象*/
    8. const ins = this;
    9. /*保存当前实例对象的两个回调函数*/
    10. ins.callbacks = [];
    11. /*实现resolve函数,将异步操作的结果给PromiseResult*/
    12. function resolve(data) {
    13. /*改变实例对象的状态*/
    14. if (ins.PromiseState == 'waiting') {
    15. ins.PromiseState = 'yes';
    16. }
    17. ins.PromiseResult = data;
    18. /*对多个then传进来的回调函数依次执行*/
    19. ins.callbacks.forEach((item) => item.solved(data))
    20. };
    21. /*实现reject函数*/
    22. function reject(data) {
    23. if (ins.PromiseState == 'waiting') {
    24. ins.PromiseState = 'no';
    25. }
    26. ins.PromiseResult = data;
    27. /*对多个then传进来的回调函数依次执行*/
    28. ins.callbacks.forEach((item) => item.rejected(data))
    29. };
    30. /*同步调用执行器,执行传进来的任务,executor被主线程执行后将异步操作放入事件队列*/
    31. try {
    32. //在这里声明resolve, reject这两个变量,根据业务逻辑选择必须resolve, reject二选一执行,将结果交给resolve, reject即可。
    33. executor(resolve, reject);
    34. } catch (error) {
    35. reject(error);
    36. }
    37. }
    38. myPromise.prototype.then = function(solved, rejected) {
    39. //solved, rejected分别对应成功和失败的回调函数。
    40. if (this.PromiseState == 'yes') {
    41. solved(this.PromiseResult); //将实例对象的结果传给回调函数进行处理
    42. }
    43. if (this.PromiseState == 'no') {
    44. rejected(this.PromiseResult);
    45. }
    46. //当主线程执行到then方法的时候还是pending状态的话就将两个回调函数保存,主线程放弃了他们,程序员不能
    47. if (this.PromiseState == 'waiting') {
    48. this.callbacks.push({
    49. solved,
    50. rejected
    51. });
    52. }
    53. };

    八,实现then返回一个Promise对象(由同步任务决定状态)

            由原生Promise类可知,then方法返回一个Promise对象,且返回结果由回调函数的执行结果决定。如下图。 

    1. function myPromise(executor) {
    2. //令executor === (f = (resolve, reject) => resolve('ok'));用于测试的操作,省去了异步操作,resolve, reject函数选择resolve执行
    3. /*置初始状态*/
    4. this.PromiseState = 'waiting';
    5. /*置初始结果*/
    6. this.PromiseResult = null;
    7. /*让ins指向实例对象*/
    8. const ins = this;
    9. /*保存当前实例对象的两个回调函数*/
    10. ins.callbacks = [];
    11. /*实现resolve函数,将异步操作的结果给PromiseResult*/
    12. function resolve(data) {
    13. /*改变实例对象的状态*/
    14. if (ins.PromiseState == 'waiting') {
    15. ins.PromiseState = 'yes';
    16. }
    17. ins.PromiseResult = data;
    18. /*对多个then传进来的回调函数依次执行*/
    19. ins.callbacks.forEach((item) => item.solved(data))
    20. };
    21. /*实现reject函数*/
    22. function reject(data) {
    23. if (ins.PromiseState == 'waiting') {
    24. ins.PromiseState = 'no';
    25. }
    26. ins.PromiseResult = data;
    27. /*对多个then传进来的回调函数依次执行*/
    28. ins.callbacks.forEach((item) => item.rejected(data))
    29. };
    30. /*同步调用执行器,执行传进来的任务,executor被主线程执行后将异步操作放入事件队列*/
    31. try {
    32. //在这里声明resolve, reject这两个变量,根据业务逻辑选择必须resolve, reject二选一执行,将结果交给resolve, reject即可。
    33. executor(resolve, reject);
    34. } catch (error) {
    35. reject(error);
    36. }
    37. }
    38. myPromise.prototype.then = function(solved, rejected) {
    39. task = (resolve, reject) => {
    40. if (this.PromiseState == 'yes') {
    41. //成功状态下记录结果,根据结果决定执行resolve还是reject
    42. let result = solved(this.PromiseResult);
    43. try {
    44. if (result instanceof myPromise) {
    45. //假如是myPromise还需要细分
    46. result.then(
    47. v => { resolve(v) },
    48. err => { reject(err) }
    49. )
    50. } else {
    51. //不是mypromise的实例,则直接使用resolve函数返回result
    52. resolve(result);
    53. }
    54. } catch (error) {
    55. reject(error);
    56. }
    57. }
    58. if (this.PromiseState == 'no') {
    59. rejected(this.PromiseResult);
    60. }
    61. if (this.PromiseState == 'waiting') {
    62. this.callbacks.push({
    63. solved,
    64. rejected
    65. });
    66. }
    67. }
    68. return new myPromise(task); //then方法需要返回一个myPromise实例,在这里返回
    69. }
  • 相关阅读:
    JavaScript 继承 - ES6的class继承用ES5如何实现?
    03.操作系统内存管理
    妙手ERP功能更新:Shopee认领配置中的主货号支持按后缀自动递增、Ozon采集箱支持批量编辑【颜色样本图】、TikTok Shop......
    LeetCode 面试题 16.02. 单词频率
    智云通CRM:如何巧妙地满足客户的价格需求?
    力扣1482.制作m束花所需的最少时间
    内涵语录
    Flink学习19:算子介绍keyBy
    HOSMEL:一种面向中文的可热插拔模块化实体链接工具包
    Python新手入门必须学会的技巧:pycharm中配置Python解释器(2022最新)
  • 原文地址:https://blog.csdn.net/weixin_44992737/article/details/126083893