手写Promise教程_then方法

Posted luckest

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写Promise教程_then方法相关的知识,希望对你有一定的参考价值。

手写Promise教程_then方法

1、Promise结构分析

console.log(new Promise((resolve, reject) => ));

通过打印Promise的实例对象,观察promise的对象结构:

分析上图,可以得出一些信息:

  • 1、promise实例对象上有PromiseState属性和PromiseResult属性
  • 2、Promise构造函数上有all方法、race方法、resolve方法、reject方法。
  • 3、Promise构造函数的原型对象上有then方法、catch方法。

这些是Promise最核心的属性和方法,手写Promise也就是去实现它们的功能。

2、构造函数

创建一个promise_test.js文件,被在html文件中中引入:

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>手写promise教程</title>
    <script src="./promise_test.js"></script>
</head>
<body>
    <script>
        new Promise((resolve, reject) => );
    </script>
</body>
</html>

promise_test.js:

function Promise(executor) 
    // 添加属性
    this.PromiseState = \'pending\';
    this.PromiseResult = undefined;

    executor(resolve, reject);

在promise_test.js文件中写上一个Promise构造函数,把JS为我们提供的原生Promise构造函数覆盖掉,然后运行代码,报错:

Uncaught ReferenceError: resolve is not defined。

为什么会出现这个错误呢?

因为在index.html中new Promise( 匿名函数(resolve, reject) ),作为实参传进来的匿名函数(resolve, reject),在构造函数内调用的时候,传入了resolve和reject实参方法,但构造函数中没有这两个方法,因此我们要在构造函数中定义resolve和reject这两个方法:

2.1、resolve 和 reject

功能分析:

  • 1、修改PromiseState的状态为fulfilled,并且PromiseState的状态只能修改一次。
  • 2、可以接收一个参数,将这个参数的值赋给PromiseResult。

index.html:

new Promise((resolve, reject) =>  resolve(\'test\'); );

promise_test.js:

function Promise(executor) 
    // 添加属性
    this.PromiseState = \'pending\';
    this.PromiseResult = undefined;

    // 定义resolve函数
    function resolve(data) 
      console.log(this.PromiseState); // undefined
    

    executor(resolve, reject);

既然要修改PromiseState的值,那么我们先尝试获取这个值,构造函数中声明的是pending,但结果却是:undefined,为什么?

this的指向问题,我们在代码中打印了了一下this,结果:Window,为什么是Window?

这里复习一下this的指向,1、普通函数中的this指向window。2、构造函数中的this指向实例对象。3、箭头函数中的this指向父级作用域的this。

ok,如果知道了这两点的话,那么就可以知道如何解决:1、将this的指向作为一个属性保存下来。2、使用箭头函数。

这里选择保存this的指向:

function Promise(executor) 
    // 添加属性
    this.PromiseState = \'pending\';
    this.PromiseResult = undefined;

    // 保存实例对象的this值
    const _this = this;
    // 定义resolve函数
    function resolve(data) 
        // 判断状态,promise状态只能更改一次
        if (_this.PromiseState !== \'pending\') return;
        // 1、修改对象的状态(promiseState)
        _this.PromiseState = \'fulfilled\'; // resolved
        // 2、设置对象的结果值(promiseResult)
        _this.PromiseResult = data;
    

    function reject(data) 
        // 判断状态,promise状态只能更改一次
        if (_this.PromiseState !== \'pending\') return;
        // 1、修改对象的状态(promiseState)
        _this.PromiseState = \'rejected\'; // rejected
        // 2、设置对象的结果值(promiseResult)
        _this.PromiseResult = data;
    

    executor(resolve, reject);

index.html:

测试1:

const p = new Promise((resolve, reject) =>  
    resolve(\'success\');
);
console.log(p);

结果1:Promise PromiseState: \'fulfilled\', PromiseResult: \'success\'

——

测试2:

const p = new Promise((resolve, reject) =>  
    reject(\'fail\');
);
console.log(p);

结果2:Promise PromiseState: \'rejected\', PromiseResult: \'fail\'

——

经过测试,PromiseState和PromiseResult成功被修改!

3、then方法

3.1、功能分析

通过1的分析,我们可以得知then方法是放在原型对象上的,这样做的目的是为了通过实例对象调用.then进行链式调用

链式调用是Promise最重要的特性,它解决了回调地狱的问题,下面我们来分析一下then方法的功能:

1、Promise.prototype.then方法:then(onResolved, onRejected) => ,

它传入两个回调函数作为形参,onResolved作为PromiseState为fulfilled时的回调函数,onRejected作为PromiseState为rejected时的回调函数。

验证代码:

const p = new Promise((resolve, reject) => 
    // resolve将PromiseState状态改为了fulfilled
    resolve(\'success\');
    // reject将PromiseState状态改为了rejected
    // reject(\'fail\');
);

p.then(value => 
    // onResolved方法的回调函数,状态时fulfilled执行
    console.log(value); // success
, reason => 
    // onRejected方法的回调函数,状态时rejected执行
    console.log(reason); // fail
);

2、then方法的返回值是一个新的promise对象,这个新的promise对象的结果状态由then指定的回调函数执行的返回值决定。

  • 如果then回调函数的返回值是:非Promise的数据。那么新promise的状态(PromiseState)是fulfilled,值(PromiseResult)是这个非Promise的数据。
  • 如果then回调函数的返回值是:Promise类型的数据,那么新的promise的状态(PromiseState)由返回值promise对象的状态决定,值(PromiseResult)也由它的值决定。
  • 如果抛出异常,新promise变成rejected,reason为抛出的异常。

验证代码:

const p = new Promise((resolve, reject) => 
    // resolve将PromiseState状态改为了fulfilled
    resolve(\'success\');
    // reject将PromiseState状态改为了rejected
    // reject(\'fail\');
);

const p2 = p.then(value => 
    // onResolved方法的回调函数,状态时fulfilled执行下面的代码
    // 返回值是value变量,非promise,也就是\'success\'
    // return value;
    // 返回值是promise对象
    return new Promise((resolve, reject) => 
        // 如果调用resolve,那么p2的PromiseStatus就是fulfilled,PromiseResult是success2
        resolve(\'success2\');
        // 如果调用reject,那么p2的PromiseStatus就是rejected,PromiseResult是fail2
        // reject(\'fail2\');
        // 如果抛出异常,那么p2的PromiseStatus就是rejected,PromiseResult是error
        // throw \'error\';
    );
, reason => 
    // onRejected方法的回调函数,状态时rejected执行下面的代码
    console.log(reason); // fail
);

console.log(p2);

3、链式调用,并且异步调用。

  • 1、then里面的代码,会按照链式调用的顺序,顺序执行。
  • 2、then里面的代码,是异步执行。

验证代码:

const p = new Promise((resolve, reject) => 
    resolve();
    console.log(\'111\');
);

const p2 = p.then(value => 
    // 没有return返回值,默认是return undefined,这个也是非promise的数据,因此状态是fulfilled,值是undefined
    console.log(\'222\');
, reason => 
    console.log(reason); // fail
);

p2.then(value => 
    console.log(\'333\');
);

console.log(\'444\');

执行结果:111 444 222 333

可以看到,同步代码先执行,执行完之后再执行then中的异步代码,并且是按照链式操作的顺序执行下来。

以上就是then方法的功能分析,下面是手写实现:

3.2、功能实现

1、实现异步执行 + 判断返回值进行不同的操作

Promise.prototype.then = function(onResolved, onRejected) 
    // then函数的返回值是一个新的promise对象
    return new Promise((resolve, reject) => 
        // 如果实例对象上的PromiseState是fulfilled,执行onResolved
        if (this.PromiseState === \'fulfilled\') 
            // 异步执行
            setTimeout(() => 
                try 
                    let result = onResolved(this.PromiseResult);
                    // 如果返回值是promise对象
                    if (result instanceof Promise) 
                        result.then(v => 
                            resolve(v);
                        , r => 
                            reject(r);
                        );
                     else 
                        // 如果返回值是非promise对象
                        resolve(result);
                    
                 catch (e) 
                    // 如果抛出异常,新promise变成rejected,reason为抛出的异常。
                    reject(e);
                
            );
        

        // 如果实例对象上的PromiseState是fulfilled,执行onRejected
        if (this.PromiseState === \'rejected\') 
            // 异步执行
            setTimeout(() => 
                try 
                    let result = onRejected(this.PromiseResult);
                    // 如果返回值是promise对象
                    if (result instanceof Promise) 
                        result.then(v => 
                            resolve(v);
                        , r => 
                            reject(r);
                        );
                     else 
                        // 如果返回值是非promise对象
                        resolve(result);
                    
                 catch (e) 
                    // 如果抛出异常,新promise变成rejected,reason为抛出的异常。
                    reject(e);
                
            );
        
    );

上述代码看似可以完美实现,但是却存在一个缺陷,以下是测试index.html:

const p = new Promise((resolve, reject) => 
    // 如果这里是异步的,出现bug:永远不会触发then方法
    setTimeout(() => 
        resolve(\'111\');
    , 1000);
);

const p2 = p.then(value => 
    console.log(\'then中:\' + value);
, reason => 
    console.log(reason);
);

上述测试,及时是等一秒甚至一百秒,then方法中的回调也不会执行,为什么?

因为这个时候p这个对象中的promiseState还处于pending状态,所以我们要在then方法中加上第三种情况,pending。

做法是:将回调函数保存起来,在resolve和reject方法中去调用,如此就可以实现链式调用

2、链式调用的实现

promise_test.js:

function Promise(executor) 
    // 添加属性
    this.PromiseState = \'pending\';
    this.PromiseResult = undefined;
    // 用于保存回调函数的数组
    this.callbacks = [];

    // 保存实例对象的this值
    const _this = this;
    // 定义resolve函数
    function resolve(data) 
        // 判断状态,promise状态只能更改一次
        if (_this.PromiseState !== \'pending\') return;
        // 1、修改对象的状态(promiseState)
        _this.PromiseState = \'fulfilled\'; // fulfilled
        // 2、设置对象的结果值(promiseResult)
        _this.PromiseResult = data;
        // 3、调用异步任务下,成功的回调函数
        setTimeout(() => 
            _this.callbacks.forEach(item => 
                item.Resolved(data);
            );
        );
    

    function reject(data) 
        // 判断状态,promise状态只能更改一次
        if (_this.PromiseState !== \'pending\') return;
        // 1、修改对象的状态(promiseState)
        _this.PromiseState = \'rejected\'; // rejected
        // 2、设置对象的结果值(promiseResult)
        _this.PromiseResult = data;
        // 3、调用异步任务下,失败的回调函数
        setTimeout(() => 
            _this.callbacks.forEach(item => 
                item.Rejected(data);
            );
        );
    

    executor(resolve, reject);


Promise.prototype.then = function(onResolved, onRejected) 
    // then函数的返回值是一个新的promise对象
    return new Promise((resolve, reject) => 
        // 如果实例对象上的PromiseState是fulfilled,执行onResolved
        if (this.PromiseState === \'fulfilled\') 
            // 异步执行
            setTimeout(() => 
                try 
                    let result = onResolved(this.PromiseResult);
                    // 如果返回值是promise对象
                    if (result instanceof Promise) 
                        result.then(v => 
                            resolve(v);
                        , r => 
                            reject(r);
                        );
                     else 
                        // 如果返回值是非promise对象
                        resolve(result);
                    
                 catch (e) 
                    // 如果抛出异常,新promise变成rejected,reason为抛出的异常。
                    reject(e);
                
            );
        

        // 如果实例对象上的PromiseState是rejected,执行onRejected
        if (this.PromiseState === \'rejected\') 
            // 异步执行
            setTimeout(() => 
                try 
                    let result = onRejected(this.PromiseResult);
                    // 如果返回值是promise对象
                    if (result instanceof Promise) 
                        result.then(v => 
                            resolve(v);
                        , r => 
                            reject(r);
                        );
                     else 
                        // 如果返回值是非promise对象
                        resolve(result);
                    
                 catch (e) 
                    // 如果抛出异常,新promise变成rejected,reason为抛出的异常。
                    reject(e);
                
            );
        

        // 如果new Promise中的函数是异步的,例如一秒之后再调用resolveo或者reject的情况
        // 后续的新promise对象的状态都是pending,都会走这里。
        // 我们就将回调函数保存起来,在resolve和reject方法中去调用
        if (this.PromiseState === \'pending\') 
            // 注意保存一下this的指向,因为下面两个都是普通函数,内部的this指向是window
            const _this = this;

            function Resolved() 
                try 
                    let result = onResolved(_this.PromiseResult);
                    // 如果返回值是promise对象
                    if (result instanceof Promise) 
                        result.then(v => 
                            resolve(v);
                        , r => 
                            reject(r);
                        );
                     else 
                        // 如果返回值是非promise对象
                        resolve(result);
                    
                 catch (e) 
                    // 如果抛出异常,新promise变成rejected,reason为抛出的异常。
                    reject(e);
                
            

            function Rejected() 
                try 
                    let result = onRejected(_this.PromiseResult);
                    // 如果返回值是promise对象
                    if (result instanceof Promise) 
                        result.then(v => 
                            resolve(v);
                        , r => 
                            reject(r);
                        );
                     else 
                        // 如果返回值是非promise对象
                        resolve(result);
                    
                 catch (e) 
                    // 如果抛出异常,新promise变成rejected,reason为抛出的异常。
                    reject(e);
                
            

            this.callbacks.push(
                Resolved,
                Rejected
            );
        
    );

3、链式调用的实现_代码优化

可以看出,上述有很多重复代码,是为了更好帮助理解,故意的。

以下则是优化后的代码promise_test.js:

function Promise(executor) 
    // 添加属性
    this.PromiseState = \'pending\';
    this.PromiseResult = undefined;
    // 用于保存回调函数的数组
    this.callbacks = [];

    // 保存实例对象的this值
    const _this = this;
    // 定义resolve函数
    function resolve(data) 
        // 判断状态,promise状态只能更改一次
        if (_this.PromiseState !== \'pending\') return;
        // 1、修改对象的状态(promiseState)
        _this.PromiseState = \'fulfilled\'; // fulfilled
        // 2、设置对象的结果值(promiseResult)
        _this.PromiseResult = data;
        // 3、调用异步任务下,成功的回调函数
        setTimeout(() => 
            _this.callbacks.forEach(item => 
                item.Resolved(data);
            );
        );
    

    function reject(data) 
        // 判断状态,promise状态只能更改一次
        if (_this.PromiseState !== \'pending\') return;
        // 1、修改对象的状态(promiseState)
        _this.PromiseState = \'rejected\'; // rejected
        // 2、设置对象的结果值(promiseResult)
        _this.PromiseResult = data;
        // 3、调用异步任务下,失败的回调函数
        setTimeout(() => 
            _this.callbacks.forEach(item => 
                item.Rejected(data);
            );
        );
    

    executor(resolve, reject);


Promise.prototype.then = function(onResolved, onRejected) 
    // 注意保存一下this的指向,因为下面普通函数,内部的this指向是window
    const _this = this;
    // then函数的返回值是一个新的promise对象
    return new Promise((resolve, reject) => 
        function handler(func) 
            try 
                let result = func(_this.PromiseResult);
                // 如果返回值是promise对象
                if (result instanceof Promise) 
                    result.then(v => 
                        resolve(v);
                    , r => 
                        reject(r);
                    );
                 else 
                    // 如果返回值是非promise对象
                    resolve(result);
                
             catch (e) 
                // 如果抛出异常,新promise变成rejected,reason为抛出的异常。
                reject(e);
            
        

        // 如果实例对象上的PromiseState是fulfilled,执行onResolved
        if (this.PromiseState === \'fulfilled\') 
            // 异步执行
            setTimeout(() => 
                handler(onResolved);
            );
        

        // 如果实例对象上的PromiseState是rejected,执行onRejected
        if (this.PromiseState === \'rejected\') 
            // 异步执行
            setTimeout(() => 
                handler(onRejected);
            );
        

        // 如果new Promise中的函数是异步的,例如一秒之后再调用resolveo或者reject的情况
        // 后续的新promise对象的状态都是pending,都会走这里。
        // 我们就将回调函数保存起来,在resolve和reject方法中去调用
        if (this.PromiseState === \'pending\') 
            this.callbacks.push(
                Resolved: () => 
                    handler(onResolved);
                ,
                Rejected: () => 
                    handler(onRejected);
                
            );
        
    );

测试代码index.html:

const p = new Promise((resolve, reject) => 
    // 开启异步
    // setTimeout(() => 
        // resolve(\'ok\');
        reject(\'no\');
    // );
);

p.then(value => 
    console.log(111);
, reason => 
    // 如果返回值是非promise类型的数据
    return reason;
)
.then(value => 
    console.log(value); // \'no\'
    // 如果返回值是promise类型的数据
    return new Promise((resolve, reject) => 
        resolve(333);
    );
, reason => 
    // ...
)
.then(value => 
    console.log(\'收到的值是:\', value); // 333
    // 如果抛出异常
    throw \'error\'
)
.then(() => 
    // ...
, reason => 
    console.log(reason); // error
)
// 如果then中是空值,什么也不传,出现bug!!!
.then()
.then(() => 
    console.log(\'我的上一个then是空值,我还可以输出吗?\');
);

最后的测试,如果then中是空值,什么也不传,出现bug!!!

4、值的穿透

解决:

Promise.prototype.then = function(onResolved, onRejected) 
    // 注意保存一下this的指向,因为下面普通函数,内部的this指向是window
    const _this = this;
    // 判断回调函数参数
    if (typeof onRejected !== \'function\') 
        onRejected = reason => 
            throw reason;
        
    
    if (typeof onResolved !== \'function\') 
        onResolved = value => value;
    
    .....

当我们不在 then 中放入参数,例:promise.then().then(),那么其后面的 then 依旧可以得到之前 then 返回的值,这叫做值的穿透

4、完整代码示例

写这个then方法,被这个then方法折磨了一整天了,中途踩了一些巨坑。

关于Promise的手写教程就先写到这里吧,catch、all、race、resolve、reject等方法的实现,会在下一篇博客中进行讲解。

这些方法相对then方法来说就简单得多了。

如果关于本篇文章有什么问题的话,可以私信我,谢谢阅读。

function Promise(executor) 
    // 添加属性
    this.PromiseState = \'pending\';
    this.PromiseResult = undefined;
    // 用于保存回调函数的数组
    this.callbacks = [];

    // 保存实例对象的this值
    const _this = this;
    // 定义resolve函数
    function resolve(data) 
        // 判断状态,promise状态只能更改一次
        if (_this.PromiseState !== \'pending\') return;
        // 1、修改对象的状态(promiseState)
        _this.PromiseState = \'fulfilled\'; // fulfilled
        // 2、设置对象的结果值(promiseResult)
        _this.PromiseResult = data;
        // 3、调用异步任务下,成功的回调函数
        setTimeout(() => 
            _this.callbacks.forEach(item => 
                item.Resolved(data);
            );
        );
    

    function reject(data) 
        // 判断状态,promise状态只能更改一次
        if (_this.PromiseState !== \'pending\') return;
        // 1、修改对象的状态(promiseState)
        _this.PromiseState = \'rejected\'; // rejected
        // 2、设置对象的结果值(promiseResult)
        _this.PromiseResult = data;
        // 3、调用异步任务下,失败的回调函数
        setTimeout(() => 
            _this.callbacks.forEach(item => 
                item.Rejected(data);
            );
        );
    

    try 
        executor(resolve, reject);
     catch (e) 
        reject(e);
    


Promise.prototype.then = function(onResolved, onRejected) 
    // 注意保存一下this的指向,因为下面普通函数,内部的this指向是window
    const _this = this;
    // 判断回调函数参数
    if (typeof onRejected !== \'function\') 
        onRejected = reason => 
            throw reason;
        
    
    if (typeof onResolved !== \'function\') 
        onResolved = value => value;
    
    // then函数的返回值是一个新的promise对象
    return new Promise((resolve, reject) => 
        function handler(func) 
            try 
                let result = func(_this.PromiseResult);
                // 如果返回值是promise对象
                if (result instanceof Promise) 
                    result.then(v => 
                        resolve(v);
                    , r => 
                        reject(r);
                    );
                 else 
                    // 如果返回值是非promise对象
                    resolve(result);
                
             catch (e) 
                // 如果抛出异常,新promise变成rejected,reason为抛出的异常。
                reject(e);
            
        

        // 如果实例对象上的PromiseState是fulfilled,执行onResolved
        if (this.PromiseState === \'fulfilled\') 
            // 异步执行
            setTimeout(() => 
                handler(onResolved);
            );
        

        // 如果实例对象上的PromiseState是rejected,执行onRejected
        if (this.PromiseState === \'rejected\') 
            // 异步执行
            setTimeout(() => 
                handler(onRejected);
            );
        

        // 如果new Promise中的函数是异步的,例如一秒之后再调用resolveo或者reject的情况
        // 后续的新promise对象的状态都是pending,都会走这里。
        // 我们就将回调函数保存起来,在resolve和reject方法中去调用
        if (this.PromiseState === \'pending\') 
            this.callbacks.push(
                Resolved: () => 
                    handler(onResolved);
                ,
                Rejected: () => 
                    handler(onRejected);
                
            );
        
    );

手写promise

promise规范
1、当实例化Promise时会立即执行
2、已经是成功态或是失败态不可再更新状态
3、让Promise支持异步
我们可以参照发布订阅模式,在执行then方法时如果还在等待态(pending),就把回调函数临时寄存到一个数组里,当状态发生改变时依次从数组中取出执行就好了。
4、链式调用
5、每个then方法都返回一个新的Promise对象(原理的核心)
6、如果then方法中显示地返回了一个Promise对象就以此对象为准,返回它的结果
7、如果then方法中返回的是一个普通值(如Number、String等)就使用此值包装成一个新的Promise对象返回。
8、如果then方法中没有return语句,就视为返回一个用Undefined包装的Promise对象
9、若then方法中出现异常,则调用失败态方法(reject)跳转到下一个then的onRejected
10、如果then方法没有传入任何回调,则继续向下传递(值的传递特性)。
function _Promise(executor){
      var _this = this;
      this.status = ‘pending‘;      //status属性保存了Promise对象的状态
      this.value = undefined;       //一个Promise对象执行成功了要有一个结果,它使用value属性保存
      this.reason = undefined;      //也有可能由于某种原因失败了,这个失败原因放在reason属性中保存
      this.onFulfilledFunc = [];   //保存成功回调
      this.onRejectedFunc = [];    //保存失败回调
      executor(resolve, reject);    //其执行器函数(executor)会立即执行

      //当Promise对象已经由pending状态改变为了成功态(resolved)或是失败态(rejected)就不能再次更改状态了
      function resolve(value){  
          if(_this.status === ‘pending‘){
            _this.value = value;//保存成功结果
            _this.onFulfilledFunc.forEach(fn=>fn(value));
            _this.status = ‘resolved‘;
          }
      }

      function reject(reason){
          if (_this.status === ‘pending‘) {
            _this.value = reason;//保存失败原因
            _this.onRejectedFunc.forEach(fn=>fn(value));
            _this.status = ‘reject‘;
          }
      }
    }

    _Promise.prototype.then = function(onFulfilled,onRejected){
      console.log(onFulfilled)
      console.log(this)

      //不论何种情况then都返回Promise对象,所以我们就实例化一个新re_promise并返回
      var re_promise = new _Promise(
          (resolve,reject)=>{
              //等待态,此时异步代码还没有走完
          if (this.status === ‘pending‘) {
            if (typeof onFulfilled === ‘function‘) {
              this.onFulfilledFunc.push(()=>{
                setTimeout(()=>{
                  try{
                    let x = onFulfilled(this.value);
                    resolvePromise(re_promise, x, resolve, reject)
                  }
                  catch(e){
                    reject(e)
                  }
                },0)
              });

            }

            if (typeof onRejected === ‘function‘) {
              this.onRejectedCallbacks.push(() => {
                setTimeout(() => {
                  try {
                    let x = onRejected(this.reason);
                    resolvePromise(re_promise, x, resolve, reject);
                  } catch (e) {
                    reject(e);
                  }
                }, 0)
              });

            }
          }

          if (this.status === ‘resolved‘) {
            //判断参数类型,是函数再执行
            console.log(typeof onFulfilled)
            if (typeof onFulfilled === ‘function‘) {
              setTimeout(() => {
                try {
                  let x = onFulfilled(this.value);
                  resolvePromise(re_promise, x, resolve, reject);
                } catch (e) {
                  reject(e);
                }
              }, 0);
            }
          }
          if (this.status === ‘rejected‘) {
            //判断参数类型,是函数再执行
            if (typeof onRejected === ‘function‘) {
              setTimeout(() => {
                try {
                  let x = onRejected(this.reason);
                  resolvePromise(re_promise, x, resolve, reject);
                } catch (e) {
                  reject(e);
                }
              }, 0);
            }
          }
          }
      )

      //接下来就处理根据上一个then方法的返回值来生成新Promise对象
      /**
       * 解析then返回值与新Promise对象
       * @param {Object} re_promise 新的Promise对象 
       * @param {*} x 上一个then的返回值
       * @param {Function} resolve re_promise的resolve
       * @param {Function} reject re_promise的reject
       */
      function resolvePromise(re_promise,x,resolve,reject){
        if (re_promise === x) {
          //不能返回自己的promise对象
          reject(new TypeError(‘Promise发生了循环引用‘));
        }
        if(x !== null && (typeof x ===‘object‘ || typeof x ===‘function‘)){
          try{
            let then = x.then; //取出then方法引用
            if(typeof then === ‘function‘){
              //如果then,则认为then为一个promise对象
              let y = then.call(x, (y) => {
                //递归调用,传入y若是Promise对象,继续循环
                resolvePromise(re_promise,y,reslove,reject);
              }, (r) => {
                reject(r);
              });
            }
            else{
              resolve(x)
            }
          }catch(e){
            //防止出现取then时报错,例如使用Object.defineProperty()
            reject(e)
          }
        }
        else{
          resolve(x);
        }
      }

      return re_promise
    }

    //可是还有一个很大的问题,目前此Promise还不支持异步代码,如果Promise中封装的是异步操作,then方法无能为力:
    let p = new _Promise((resolve, reject) => {
        // resolve(‘同步‘);
        setTimeout(() => {
          resolve(‘异步‘);
        },1500);
      })
      // }).then(data=>console.log(data));

      // p.then(data => console.log(data)); //没有任何结果
      // p.then(function(data){
      //   console.log(data)
      // }); //没有任何结果

      p.then(data => {return 2;}).then(data=>{
        console.log(data)
      });

 

以上是关于手写Promise教程_then方法的主要内容,如果未能解决你的问题,请参考以下文章

手写promise

手写promise异步状态修改then方法返回来的结果

JS手写面试题 --- Promise 以及相关方法的实现

手写promise进阶版本

手写Promise的实现

手写Promise的实现