Promise

Promise 是 JavaScript 中处理异步操作的重要工具,它解决了回调地狱问题,提供了链式调用和更好的错误处理方式。本文详细介绍了 Promise 的概念、API、工作原理,并逐步展示了如何手写一个 Promise,以及 Promise 与 async/await 的关系和使用。
摘要由CSDN通过智能技术生成

目录

一、Promise 的理解和使用

1.1 Promise 是什么?

1.1.1 理解

1.1.2 promise 的改变状态

1.1.3 promise 的基本流程

1.2 为什么要用 Promise ?

1.2.1 指定回调函数的方式更加灵活

1.2.2 支持链式调用,可以解决回调地狱问题

1.2.3 案例理解

1.3 Promise API 

1.3.1 Promise 构造函数:Promise(excutor) { }

1.3.2  Promise.prototype.then 方法: then((value) => {},  (reason) => {}) 

1.3.3 Promise.prototype.catch 方法:catch((reason) => {})

1.3.4  Promise.resolve 方法: Promise.resolve(value)

1.3.5  Promise.reject 方法: Promise.reject(reason) 

1.3.6  Promise.all 方法: Promise.all(promise)  

1.3.7  Promise.race 方法: Promise.race(promise)  

1.4 promise 的几个关键问题

1.4.1 如何改变 promise 的状态?

1.4.2 一个 promise 指定多个 成功 / 失败 回调函数,都会调用吗?

1.4.3 改变 promise 状态和指定回调函数谁先谁后?

1.4.4 promise.then()  返回的新的 promise 的结果状态由什么决定? 

1.4.5 promise 如何串连多个操作任务?

1.4.6 promise 异常传透?

1.4.7 中断 promise 链?

二、自定义(手写)Promise

2.1 定义整体机构 

2.2 执行器函数的 两个参数 resolve 和 reject 改变状态的函数结构搭建

2.3 resolve 和 reject 代码实现

2.4 throw 抛出异常改变状态

2.5 状态只能修改一次

2.6 then方法执行回调

2.7 异步任务 then 方法实现

2.8 指定多个回调函数

2.9 同步任务 then 返回结果

2.10 异步任务 then 返回结果

2.11 catch 方法与异常穿透

2.12 Promise.resolve 封装

2.13 Promise.reject  封装

2.14 Promise.all 封装

2.15 Promise.race 封装

2.16 回调函数 异步调用

2.16.1 完整版1.0 

2.17 class 封装

2.17.1 完整版2.0 

三、async 与 await

3.1 mdn 文档

3.2  async 函数

3.3 await 表达式

3.4 注意

3.5 案例

3.5.1nodejs  获取文件内容

3.5.2 async与await结合发送AJAX

3.5.3 可以和axios结合使用,axios返回的是一个promise 


练习代码地址:GitHub - climber-lx/x-Promise

一、Promise 的理解和使用

1.1 Promise 是什么?

1.1.1 理解

1.抽象表达

1.Promise 是一门新的技术(ES6规范)。

2.Promise 是 JS 中进行异步编程的新解决方案

        备注:旧方案是单纯使用回调函数

2.集体表达

1.从语法上来说: Promise 是一个构造函数

2.从功能是哪个来说:promise 对象用来封装一个异步操作并可以获取其成功/失败的结果值。

异步编程

node 中的 fs 文件操作:

        require('fs').readFile('./index.html',(err, data) => {});

数据库操作

AJAX

        $.get('/server', (data)=>{})

定时器

        setTimeout(()=>{},2000)

1.1.2 promise 的改变状态

promise的状态

实例中的一个属性 【PromiseStatus】

pedding        未决定的

resolved / fullfilled        成功

rejected        失败

Promise 对象的值

实例中的一个属性 【PromiseResult】    then 方法return的值

保存着异步任务 【成功/失败】的结果

1. pending变为 resolved

2. pending变为 rejected

说明:只有这2种,且一个 promise 对象只能改变一次

        无论变成成功还是失败,都会有一个结果数据

        成功的结果数据一般称为value,失败的结果一般称为reason

1.1.3 promise 的基本流程

1.2 为什么要用 Promise ?

1.2.1 指定回调函数的方式更加灵活

1.旧的:必须在启动异步任务前指定

2.promise:启动异步任务 => 返回 promise 对象 => 给 promise 对象绑定回调函数(甚至可以异步任务技术后指定/多个)

1.2.2 支持链式调用,可以解决回调地狱问题

1.什么是回调地狱?

        回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件。

2.回调地狱的缺点?

        不便于阅读、不便于异常处理

3.解决方案?

        promise 链式调用

4.终极解决方案?

        promise 和 async结合使用。

1.2.3 案例理解

1.中奖概率

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>基本使用</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu"
        crossorigin="anonymous">
</head>

<body>
    <div class="container">
        <h2 class="page-header">Promise 初体验</h2>
        <button class="btn btn-primary" id="btn">点击抽奖</button>
    </div>
    <script>
        // 生成随机数
        function rand(m, n) {
            return Math.ceil(Math.random() * (n - m + 1) + m - 1);
        }

        /**
            点击按钮,2s后显示是否中奖(30%概率中奖)
            若中奖弹出  恭喜恭喜,奖品为10万RMB 劳斯莱斯优惠券
            若未中奖弹出  再接再厉
        */

        // 获取元素对象
        const btn = document.querySelector('#btn');
        btn.addEventListener('click', function () {
            // 定时器
            // setTimeout(() => {
            //     let n = rand(1, 100);
            //     if (n <= 30) {
            //         alert('恭喜恭喜,奖品为10万RMB 劳斯莱斯优惠券');
            //     } else {
            //         alert('再接再厉');
            //     }
            // }, 1000);

            // promise 形式实现
            // resolve 解决 函数类型的数据
            // reject 拒绝 函数类型的数据
            const p = new Promise((resolve, reject) => {
                setTimeout(() => {
                    let n = rand(1, 100);
                    if (n <= 30) {
                        resolve(n); // 将 promise 对象的状态设置为 【成功】
                    } else {
                        reject(n); // 将 promise 对象的状态设置为 【失败】
                    }
                }, 1000);
            })
            p.then((value) => {
                alert('恭喜恭喜,奖品为10万RMB 劳斯莱斯优惠券,您的中奖号码为' + value);
            }, (reason) => {
                alert('再接再厉,您的号码为' + reason);
            })
        })
    </script>
</body>

</html>

2.获取文件内容

const fs = require('fs');

// 回调函数 形式
// fs.readFile('./resource/content.txt', (err, data) => {
//     // 如果出错
//     if (err) throw err;
//     // 输出文件内容
//     console.log(data.toString());
// })

// promise 形式
let p = new Promise((resolve, reject) => {
    fs.readFile('./resource/content.txt', (err, data) => {
        // 如果出错
        if (err) reject(err);
        // 输出文件内容
        resolve(data);
    })
});
p.then((value) => {
    console.log(value.toString());
}, (reason) => {
    console.log(reason);
})

3.发送ajax请求

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>promise时间练习</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu"
        crossorigin="anonymous">
</head>

<body>
    <div class="container">
        <h2 class="page-header">Promise 初体验</h2>
        <button class="btn btn-primary" id="btn">点击抽奖</button>
    </div>
    <script>
        // 接口地址:https://api.apiopen.top/getJoke
        const btn = document.querySelector('#btn');
        let url = "https://api.apiopen.top/getJoke";

        btn.addEventListener('click', function () {
            const p = new Promise((resolve, reject) => {
                // 1.创建对象
                const xhr = new XMLHttpRequest();
                // 2.初始化
                xhr.open('GET', url);
                // 3.发送
                xhr.send();
                // 4.处理响应结果
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        if (xhr.status >= 200 & xhr.status < 300) {
                            resolve(xhr.response);
                        } else {
                            reject(xhr.status);
                        }
                    }
                }
            })
            p.then((value) => {
                console.log(value);
            }, (reason) => {
                console.log(reason);
            })
        })
    </script>
</body>

</html>

 4.封装- fs模块练习

/**
 * 封装一个函数 minReadFile 读取文件内容
 * 参数:path 文件路径
 * 返回:promise对象
 * 
 */

function minReadFile(path) {
    return new Promise((resolve, reject) => {
        require('fs').readFile(path, (err, data) => {
            // 判断
            if (err) reject(err);
            resolve(data);
        })
    })
}

minReadFile('./resource/content.txt').then((value) => {
    console.log(value.toString());
}, (reason) => {
    console.log(reason);
})

5.使用node util

/**
 * util.promisify 方法
 */

// 引入 util 模块
const util = require('util');
// 引入fs模块
const fs = require('path');
// 返回一个新的函数
let mineReadFile = util.promisify(fs.readFile);

mineReadFile('./resource/content.txt').then((value) => {
    console.log(value.toString());
}, (reason) => {
    console.log(reason);
})

6.封装-发送ajax 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>promise封装AJAX练习</title>
</head>

<body>
    <script>
        /*
            封装一个函数 sendAJAX 发送 GET AJAX 请求
            参数 URL
            返回结果 promise 对象
        */
        function sendAJAX(url) {
            return new Promise((resolve, reject) => {
                // 1.创建对象
                const xhr = new XMLHttpRequest();
                // 指定返回的数据格式
                xhr.responseType = 'json';
                // 2.初始化
                xhr.open('GET', url);
                // 3.发送
                xhr.send();
                // 4.处理响应结果
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        if (xhr.status >= 200 & xhr.status < 300) {
                            resolve(xhr.response);
                        } else {
                            reject(xhr.status);
                        }
                    }
                }
            })
        }
        let url = "https://api.apiopen.top/getJoke";
        sendAJAX(url).then((value) => {
            console.log(value);
        }, (reason) => {
            console.log(reason);
        })
    </script>
</body>

</html>

1.3 Promise API 

1.3.1 Promise 构造函数:Promise(excutor) { }

(1) excutor 函数:执行器       (resolve, reject) => { }

(2) resolve 函数:内部定义成功时调用的函数;resolve(result)。  回调函数:value => { }

(3) reject 函数:内部定义失败时调用的函数;reject(error)。回调函数:reason => { }

说明:excutor 会在 Promise 内部立即同步调用,异步操作在执行器中执行

// excutor 函数: 执行器 ((resolve, reject) => {})
let p = new Promise((resolve, reject) => {
    
})

1.3.2  Promise.prototype.then 方法: then((value) => {},  (reason) => {}) 

(1) resolve() 函数:成功的回调函数。value => { }

(2) reject() 函数:失败的回调函数。reason => { }

说明:指定用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调返回一个新的 promise 对象。

// excutor 函数 ((resolve, reject) => {})
let p = new Promise((resolve, reject) => {
    // 同步调用的
    console.log(111);
    // resolve('success');
    reject('faild');
})

// then(参数1,参数2)
// 参数1 和 参数2 都是函数类型
// 参数1: resolve():成功的回调函数
// 参数2: reject():失败的回调函数
// 参数2可以不写,只写一个参数时为成功的回调函数。
p.then((value) => {
    console.log(value); // success
}, (reason) => {
    console.log(reason);    //faild
})

console.log(p);
// 如果then 方法中不设置返回值,then方法返回结果为一个成功的promise,返回值为 undefined
// 如果有返回值,类型为 非promise 时,then方法返回一个成功的promise,返回值为 输出的返回值。
// 如果有返回值且为promise类型,则根据返回的promise来决定返回的promise的状态和结果。
// 如果then中抛出异常,则根据当前的状态返回一个promise对象,返回值为抛出的值

1.3.3 Promise.prototype.catch 方法:catch((reason) => {})

(1) reject() 函数:失败的回调函数。reason => { }

let p = new Promise((resolve, reject) => {
    // 同步调用的
    console.log(111);
    // resolve('success');
    reject('faild');
})

// reject() 错误的回调函数
p.catch((reason) => {
    console.log(reason);    //faild
})

1.3.4  Promise.resolve 方法: Promise.resolve(value)

(1) value: 成功的数据或promise对象

说明:返回一个 成功/失败 的 promise 对象

        如果传入的参数为 非Promise 类型的对象,则返回的结果为成功 promise,结果为传入的值。 

        如果传入的参数为 Promise对象,则参数的结果决定了 resolve 的状态和结果 【即实例对象的状态和结果】

// 如果传入的参数为 非Promise 类型的对象,则返回的结果为成功 promise,结果为传入的值。
let p1 = Promise.resolve(521);
console.log(p1); //Promise {<fulfilled>: 521}
// 如果传入的参数为 Promise对象,则参数的结果决定了 resolve 的状态和结果 【即实例对象的状态和结果】
let p2 = Promise.resolve(new Promise((resolve, reject) => {
    // resolve('ok');
    reject('error');
}))
// console.log(p2); //成功时: Promise {<fulfilled>: 'ok'}
console.log(p2); //失败时: Promise {<rejected>: 'error'}

let re = p2.catch((reason) => {
    console.log(reason); //error
})
console.log(re);    //Promise {<fulfilled>: undefined}

1.3.5  Promise.reject 方法: Promise.reject(reason) 

(1) reason:失败的原因

说明:返回一个失败的 promise 对象,PromiseResult为输入的 reason

let p1 = Promise.reject(521);
let p2 = Promise.reject('12');
let p3 = Promise.reject(new Promise((resolve, reject) => {
    resolve('ok');
}))
console.log(p1);    // Promise {<rejected>: 521}
console.log(p2);    // Promise {<rejected>: '12'}
console.log(p3);    // Promise {<rejected>: Promise}

1.3.6  Promise.all 方法: Promise.all(promise)  

(1) promise:包含n个 promise的数组

说明:返回一个新的promise,所有的 promise 都成功才成功,只要有一个失败就是直接失败。

let p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('ok');
    }, 1000);
})
// let p2 = Promise.resolve('Success');
let p2 = Promise.reject('error');
let p3 = Promise.resolve('Oh Yeah');

const result = Promise.all([p1, p2, p3]);
console.log(result);

1.3.7  Promise.race 方法: Promise.race(promise)  

(1) promise:包含n个 promise的数组

说明:返回一个新的promise,第一个完成的 promise 的结果状态就是最终的结果状态。无论是成功还是失败的结果。

let p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('ok');
    }, 100);
})
let p2 = Promise.resolve('success');
let p3 = Promise.resolve('Oh Yeah');

const result = Promise.race([p1, p2, p3]);
// 哪个先返回,就是哪个,只要一个失败
console.log(result); //success

1.4 promise 的几个关键问题

1.4.1 如何改变 promise 的状态?

(1) resolve(value): 如果当前是 pending就会变为 resolved

(2) reject(reason): 如果当前是 pending就会变为 rejected

(3) 抛出异常:如果当前是 pending就会变为 rejected

let p = new Promise((resolve, reject) => {
    // 1.resolve 函数
    // resolve('ok');  // pedding => fufilld(resolved)
    // 2.reject 函数
    // reject('error');    // pedding => rejected
    // 3.抛出错误
    throw '出问题了';   // pedding => rejected
})
console.log(p);

1.4.2 一个 promise 指定多个 成功 / 失败 回调函数,都会调用吗?

当 promise 改变为对应状态时都会调用。

let p = new Promise((resolve, reject) => {
    resolve('ok');
})

// 指定回调 -1
p.then(value => {
    console.log(value); //ok
})

// 指定回调 -2
p.then(value => {
    console.log(value); //ok
})

1.4.3 改变 promise 状态和指定回调函数谁先谁后?

(1) 都有可能,正常情况下是先指定回调函数再改变状态,但也可以先改变状态再指定回调。

(2) 如何先改变状态再指定回调?

  • 在执行器中直接调用 resolve() / reject()
  • 延迟更长时间才调用 then()

(3) 什么时候才能得到数据?

  • 如果先指定的回调,那就状态发生改变时,回调函数就会调用,得到数据
  • 如果先改变状态,那当指定回调时,回调函数就会调用,得到数据

自己的理解:   

        改变 promise 状态和指定回调函数谁先谁后

        指定回调函数即为声明回调函数

        如果 执行器 函数中如同步操作,则先改变状态,在指定回调函数,在指定回调函数

        如果 执行器 函数中是异步操作,则先指定回调函数【为同步操作】,等状态改变时,在执行回调函数。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>改变 promise 状态和指定回调函数谁先谁后</title>
</head>

<body>
    <script>
        // 改变 promise 状态和指定回调函数谁先谁后
        // 指定回调函数即为声明回调函数
        // 如果 执行器 函数中如同步操作,则先改变状态,在指定回调函数,在指定回调函数
        // 如果 执行器 函数中是异步操作,则先指定回调函数【为同步操作】,等状态改变时,在执行回调函数。
        let p = new Promise((resolve, reject) => {
            console.log(444);
            setTimeout(() => {
                resolve('ok')
            }, 0);
        })
        console.log(111);
        setTimeout(() => {
            console.log(555);
            setTimeout(() => {
                console.log(`5555-setTimeout`)
            }, 0);
            p.then(() => { console.log(`5555-then`) });
        }, 0);
        p.then((value) => {
            console.log(222);
        }, (reason) => {

        })
        setTimeout(() => {
            console.log(666);
        }, 0);
        console.log(333);

        // 输出顺序为 444 111 333 222  555 666
        // 分析:执行器函数是同步操作,更改状态时异步操作,所以先指定回调函数,等状态状态,在执行回调函数。
        // 整体结果分析:
        // 执行顺序: 先执行同步操作 -->  在执行异步的微任务  --> 异步的宏任务 --> 微任务  --> 宏任务
    </script>
</body>

</html>

 代码执行顺序:同步操作 ==》 异步的微任务【如then()】 ==》 异步的宏任务 ==》异步微任务 ==》 异步微任务      

注意:放入事件循环的顺序,先放先执行。

1.4.4 promise.then()  返回的新的 promise 的结果状态由什么决定? 

(1) 简单表达:由 then() 指定的回调函数执行的结果决定

(2) 详细表达:

  1. 如果抛出异常,新的 promise 变为 rejected, reason 为抛出的异常。
  2. 如果返回的是非promise的任意值,新的promise变为 resolved【fulfilled】,value为返回的值。
  3. 如果返回的是另一个新的promise,此promise的结果就会成为新的 promise 的结果。
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>then方法的返回结果由什么决定</title>
</head>

<body>
    <script>
        let p = new Promise((resolve, reject) => {
            resolve('ok');
        })
        // 执行 then 方法
        let result = p.then(value => {
            console.log(value);
            // 1.抛出错误
            // throw '出了问题';
            // 2.返回结果是 非 Promise 类型对象
            // return 522;
            // 3.返回结果是 Promise 对象
            return new Promise((resolve, reject) => {
                // resolve('success');
                reject('error');
            })
        }, reason => {
            console.warn(reason);
        })
        // 1.抛出错误
        // console.log(result); // rejected    出了问题
        // 2.返回结果是 非 Promise 类型对象
        // console.log(result);    // fulfilled 522
        // 3.返回结果是 Promise 对象  成功时
        // console.log(result);    // fulfilled 522
        // 3.返回结果是 Promise 对象  成功时
        console.log(result);    // rejected error

    </script>
</body>

</html>

1.4.5 promise 如何串连多个操作任务?

(1) promise 的 then() 返回一个新的 promise,可以开成 then() 的链式调用。

(2) 通过 then 的链式调用串连多个 同步/异步 任务。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>如何串联多个任务</title>
</head>

<body>
    <script>
        let p = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('ok');
            }, 1000);
        })

        p.then(value => {
            return new Promise((resolve, reject) => {
                resolve('success');
            })
        }).then(value => {
            console.log(value);  // success
            // return '我指定了返回值'
        }).then(value => {
            console.log(value); // undefined  
            // 如果上一步 指定 返回值
            // console.log(value); // 我指定了返回值
        })
        // 打印 undefined 的原因: 第二个then没有指定返回值,即返回undefined
        // 如果第二个then指定返回值,就打印返回值
    </script>
</body>

</html>

1.4.6 promise 异常传透?

(1) 当使用 promise 的 then 链式调用,可以在最后指定失败的回调。

(2)  前面任何操作出了异常,都会传到最后失败的回调中处理。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>异常穿透</title>
</head>

<body>
    <script>
        let p = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('ok');
                // reject('eror');
            }, 1000);
        })

        p.then(value => {
            console.log(111);
            throw '失败啊'
        }).then(value => {
            console.log(222);
        }).then(value => {
            console.log(333);
        }).catch((reason) => {
            console.warn(reason);
        })

        // 只要出错就会执行 catch 方法,所以一般只要在末尾指定失败的回调即可,中间有错也会执行。即为穿透
    </script>
</body>

</html>

1.4.7 中断 promise 链?

(1) 当使用 promise 的 then 链式调用时,在中间中断,不再调用后面的回调函数。

(2) 办法:在回调函数中返回一个 pedding 状态的 promise 对象。【有且只有这一种办法】

(3) 注意:失败的reject() 和 抛出异常的办法都不行,会调用 catch 回调函数。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>如何中断Promise链条</title>
</head>

<body>
    <script>
        let p = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('ok');
            }, 1000);
        })

        p.then(value => {
            console.log(111);
            // 有且只有这一种办法
            // return 一个 状态为pedding的 promise 对象
            return new Promise(() => { });
        }).then(value => {
            console.log(222);
        }).then(value => {
            console.log(333);
        }).catch((reason) => {
            console.warn(reason);
        })
        // 如果是抛出异常 和 执行reject()函数 是会执行catch回调函数,并不能中断promise链条。
        // 只有 return 一个 处于pending状态的 promise 才会中断
    </script>
</body>

</html>

二、自定义(手写)Promise

2.1 定义整体机构 

// 初始化搭建
function Promise() {

}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {

}

2.2 执行器函数的 两个参数 resolve 和 reject 改变状态的函数结构搭建

// 初始化搭建
function Promise(executor) {

    // resolve 函数
    function resolve(data) {

    }
    // reject 函数
    function reject(data) {

    }

    // 同步调用 【执行器函数】
    executor(resolve, reject);
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {

}

2.3 resolve 和 reject 代码实现

// 初始化搭建
function Promise(executor) {
    // 添加属性
    this.promiseStatus = "pending";
    this.promiseResult = null;
    // 保存实例对象的 this 的值
    const self = this;  // 一般用 self  _this that
    // resolve 函数
    function resolve(data) {
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'fulfiied';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
    }
    
    // reject 函数
    function reject(data) {
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'rejected';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
    }

    // 同步调用 【执行器函数】
    executor(resolve, reject);
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {

}

2.4 throw 抛出异常改变状态

使用 try catch 捕获抛出的异常

// 初始化搭建
function Promise(executor) {
    // 添加属性
    this.promiseStatus = "pending";
    this.promiseResult = null;
    // 保存实例对象的 this 的值
    const self = this;  // 一般用 self  _this that
    // resolve 函数
    function resolve(data) {
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'fulfiied';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
    }

    // reject 函数
    function reject(data) {
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'rejected';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
    }
    try {
        // 同步调用 【执行器函数】
        executor(resolve, reject);
    } catch (error) {
        reject(error);
    }
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {

}

2.5 状态只能修改一次

即:状态不为 pending 就不能执行函数,需要return 出去。

// 初始化搭建
function Promise(executor) {
    // 添加属性
    this.promiseStatus = "pending";
    this.promiseResult = null;
    // 保存实例对象的 this 的值
    const self = this;  // 一般用 self  _this that
    // resolve 函数
    function resolve(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'fulfiied';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
    }

    // reject 函数
    function reject(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'rejected';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
    }
    try {
        // 同步调用 【执行器函数】
        executor(resolve, reject);
    } catch (error) {
        reject(error);
    }
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {

}

2.6 then方法执行回调

根据对象当前的状态,判断执行 成功的回调函数还是失败的回调函数。

回调函数穿的参数为对象结果的值。

// 初始化搭建
function Promise(executor) {
    // 添加属性
    this.promiseStatus = "pending";
    this.promiseResult = null;
    // 保存实例对象的 this 的值
    const self = this;  // 一般用 self  _this that
    // resolve 函数
    function resolve(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'fulfiied';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
    }

    // reject 函数
    function reject(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'rejected';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
    }
    try {
        // 同步调用 【执行器函数】
        executor(resolve, reject);
    } catch (error) {
        reject(error);
    }
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
    // 调用回调函数  根据对象的状态判断
    if (this.promiseStatus === "fulfiied") {
        onResolved(this.promiseResult);
    }
    if (this.promiseStatus === "rejected") {
        onRejected(this.promiseResult);
    }
}

2.7 异步任务 then 方法实现

当异步改变执行改变状态的 resolve 和 reject 时,需要改变之后才去执行then方法。

方法:当状态为pending时已经执行then方法,就将回调函数存起来,在发状态改变之后去调回调函数。

// 初始化搭建
function Promise(executor) {
    // 添加属性
    this.promiseStatus = "pending";
    this.promiseResult = null;
    // 声明属性
    this.callback = {};
    // 保存实例对象的 this 的值
    const self = this;  // 一般用 self  _this that
    // resolve 函数
    function resolve(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'fulfiied';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        if (self.callback.onResolved) {
            self.callback.onResolved(data);
        }
    }

    // reject 函数
    function reject(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'rejected';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        if (self.callback.onRejected) {
            self.callback.onRejected(data);
        }
    }
    try {
        // 同步调用 【执行器函数】
        executor(resolve, reject);
    } catch (error) {
        reject(error);
    }
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
    // 调用回调函数  根据对象的状态判断
    if (this.promiseStatus === "fulfiied") {
        onResolved(this.promiseResult);
    }
    if (this.promiseStatus === "rejected") {
        onRejected(this.promiseResult);
    }
    // 状态三种,判断为pending的时候
    if (this.promiseStatus === "pending") {
        this.callback = {
            onResolved: onResolved,
            onRejected: onRejected
        }
    }
}

2.8 指定多个回调函数

当指定多个回调函数时,发现只能执行一次,因为:只保存了一次的回调函数,后面的会覆盖前面的。

解决办法:需要将所有的回调函数都保存起来,等到状态改变再去调用回调函数。

        1、将之前的存回调函数的属性 callback改为数组。

        2、在保存是使用push保存,调用时循环调用callback中的回调函数。

// 初始化搭建
function Promise(executor) {
    // 添加属性
    this.promiseStatus = "pending";
    this.promiseResult = null;
    // 声明属性
    this.callback = [];
    // 保存实例对象的 this 的值
    const self = this;  // 一般用 self  _this that
    // resolve 函数
    function resolve(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'fulfiied';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onResolved(data);
        });
    }

    // reject 函数
    function reject(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'rejected';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onRejected(data);
        });
    }
    try {
        // 同步调用 【执行器函数】
        executor(resolve, reject);
    } catch (error) {
        reject(error);
    }
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
    // 调用回调函数  根据对象的状态判断
    if (this.promiseStatus === "fulfiied") {
        onResolved(this.promiseResult);
    }
    if (this.promiseStatus === "rejected") {
        onRejected(this.promiseResult);
    }
    // 状态三种,判断为pending的时候
    if (this.promiseStatus === "pending") {
        // 保存回调函数
        this.callback.push({
            onResolved: onResolved,
            onRejected: onRejected
        })
    }
}

2.9 同步任务 then 返回结果

then方法的返回结果是一个undefined,但是需要返回一个promise对象,并指定结果。

根据之前的阐述的不同情况来完成。

        1.返回是一个非promise

        2.返回是一个promise

        3.对抛出异常的捕获

// 初始化搭建
function Promise(executor) {
    // 添加属性
    this.promiseStatus = "pending";
    this.promiseResult = null;
    // 声明属性
    this.callback = [];
    // 保存实例对象的 this 的值
    const self = this;  // 一般用 self  _this that
    // resolve 函数
    function resolve(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'fulfiied';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onResolved(data);
        });
    }

    // reject 函数
    function reject(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'rejected';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onRejected(data);
        });
    }
    try {
        // 同步调用 【执行器函数】
        executor(resolve, reject);
    } catch (error) {
        reject(error);
    }
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
    return new Promise((resolve, reject) => {
        // 调用回调函数  根据对象的状态判断
        if (this.promiseStatus === "fulfiied") {
            try {
                // 获取回调函数的执行结果
                let result = onResolved(this.promiseResult);
                if (result instanceof Promise) {
                    // 如果是一个promise
                    result.then((v) => {
                        resolve(v);
                    }, (r) => {
                        reject(r);
                    })
                } else {
                    // 结果的状态为 【成功】
                    resolve(result);
                }
            } catch (error) {
                reject(error)
            }
        }
        if (this.promiseStatus === "rejected") {
            try {
                // 获取回调函数的执行结果
                let result = onRejected(this.promiseResult);
                if (result instanceof Promise) {
                    // 如果是一个promise
                    result.then((v) => {
                        resolve(v);
                    }, (r) => {
                        reject(r);
                    })
                } else {
                    // 结果的状态为 【成功】
                    resolve(result);
                }
            } catch (error) {
                reject(error)
            }
        }
        // 状态三种,判断为pending的时候
        if (this.promiseStatus === "pending") {
            // 保存回调函数
            this.callback.push({
                onResolved: onResolved,
                onRejected: onRejected
            })
        }
    })
}

2.10 异步任务 then 返回结果

异步的时候,没有调返回的promise对象,导致状态一直为pending,结果为undefined。

解决办法:为pending时,改变状态的函数是在Promise中的resolve或reject调的,执行的是保存的回调函数。适配保存时的回调函数。

重复代码过多,封装一个函数。callback(type)

此文件为一个完成的then方法实现。 但是没有考虑then只有一个参数或者没有参数的情况。

// 初始化搭建
function Promise(executor) {
    // 添加属性
    this.promiseStatus = "pending";
    this.promiseResult = null;
    // 声明属性
    this.callback = [];
    // 保存实例对象的 this 的值
    const self = this;  // 一般用 self  _this that
    // resolve 函数
    function resolve(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'fulfiied';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onResolved(data);
        });
    }

    // reject 函数
    function reject(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'rejected';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onRejected(data);
        });
    }
    try {
        // 同步调用 【执行器函数】
        executor(resolve, reject);
    } catch (error) {
        reject(error);
    }
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
    const self = this;
    return new Promise((resolve, reject) => {
        // 重复代码太多,封装函数
        function callback(type) {
            try {
                // 获取回调函数的执行结果
                let result = type(self.promiseResult);
                if (result instanceof Promise) {
                    // 如果是一个promise
                    result.then((v) => {
                        resolve(v);
                    }, (r) => {
                        reject(r);
                    })
                } else {
                    // 结果的状态为 【成功】
                    resolve(result);
                }
            } catch (error) {
                reject(error)
            }
        }
        // 调用回调函数  根据对象的状态判断
        if (this.promiseStatus === "fulfiied") {
            callback(onResolved);
        }
        if (this.promiseStatus === "rejected") {
            callback(onRejected);
        }
        // 状态三种,判断为pending的时候
        if (this.promiseStatus === "pending") {
            // 保存回调函数
            this.callback.push({
                onResolved: function () {
                    callback(onResolved);
                },
                onRejected: function () {
                    callback(onRejected);
                },
            })
        }
    })
}

2.11 catch 方法与异常穿透

调用then方法来完成,第一个参数可以传一个undefined。

注意:在then方法中需要判断,参数为空时的操作。

// 初始化搭建
function Promise(executor) {
    // 添加属性
    this.promiseStatus = "pending";
    this.promiseResult = null;
    // 声明属性
    this.callback = [];
    // 保存实例对象的 this 的值
    const self = this;  // 一般用 self  _this that
    // resolve 函数
    function resolve(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'fulfiied';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onResolved(data);
        });
    }

    // reject 函数
    function reject(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'rejected';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onRejected(data);
        });
    }
    try {
        // 同步调用 【执行器函数】
        executor(resolve, reject);
    } catch (error) {
        reject(error);
    }
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
    const self = this;
    // 判断 回调函数参数
    if (typeof onRejected !== 'function') {
        onRejected = reason => {
            throw reason;
        }
    }
    if (typeof onResolved !== 'function') {
        onResolved = value => value
    }
    return new Promise((resolve, reject) => {
        // 重复代码太多,封装函数
        function callback(type) {
            try {
                // 获取回调函数的执行结果
                let result = type(self.promiseResult);
                if (result instanceof Promise) {
                    // 如果是一个promise
                    result.then((v) => {
                        resolve(v);
                    }, (r) => {
                        reject(r);
                    })
                } else {
                    // 结果的状态为 【成功】
                    resolve(result);
                }
            } catch (error) {
                reject(error)
            }
        }
        // 调用回调函数  根据对象的状态判断
        if (this.promiseStatus === "fulfiied") {
            callback(onResolved);
        }
        if (this.promiseStatus === "rejected") {
            callback(onRejected);
        }
        // 状态三种,判断为pending的时候
        if (this.promiseStatus === "pending") {
            // 保存回调函数
            this.callback.push({
                onResolved: function () {
                    callback(onResolved);
                },
                onRejected: function () {
                    callback(onRejected);
                },
            })
        }
    })
}

// 添加catch方法
Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected);
}

2.12 Promise.resolve 封装

分两种情况

        1.参数为promise

        2.参数为非promise

// 初始化搭建
function Promise(executor) {
    // 添加属性
    this.promiseStatus = "pending";
    this.promiseResult = null;
    // 声明属性
    this.callback = [];
    // 保存实例对象的 this 的值
    const self = this;  // 一般用 self  _this that
    // resolve 函数
    function resolve(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'fulfiied';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onResolved(data);
        });
    }

    // reject 函数
    function reject(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'rejected';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onRejected(data);
        });
    }
    try {
        // 同步调用 【执行器函数】
        executor(resolve, reject);
    } catch (error) {
        reject(error);
    }
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
    const self = this;
    // 判断 回调函数参数
    if (typeof onRejected !== 'function') {
        onRejected = reason => {
            throw reason;
        }
    }
    if (typeof onResolved !== 'function') {
        onResolved = value => value
    }
    return new Promise((resolve, reject) => {
        // 重复代码太多,封装函数
        function callback(type) {
            try {
                // 获取回调函数的执行结果
                let result = type(self.promiseResult);
                if (result instanceof Promise) {
                    // 如果是一个promise
                    result.then((v) => {
                        resolve(v);
                    }, (r) => {
                        reject(r);
                    })
                } else {
                    // 结果的状态为 【成功】
                    resolve(result);
                }
            } catch (error) {
                reject(error)
            }
        }
        // 调用回调函数  根据对象的状态判断
        if (this.promiseStatus === "fulfiied") {
            callback(onResolved);
        }
        if (this.promiseStatus === "rejected") {
            callback(onRejected);
        }
        // 状态三种,判断为pending的时候
        if (this.promiseStatus === "pending") {
            // 保存回调函数
            this.callback.push({
                onResolved: function () {
                    callback(onResolved);
                },
                onRejected: function () {
                    callback(onRejected);
                },
            })
        }
    })
}

// 添加catch方法
Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected);
}

// 添加 resolve 方法
Promise.resolve = function (value) {
    // 返回 promise 对象
    return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
            value.then((v) => {
                resolve(v);
            }, (r) => {
                reject(r);
            })
        } else {
            resolve(value);
        }
    })
}

2.13 Promise.reject  封装

无论参数为什么,都返回一个失败的promise对象。

// 初始化搭建
function Promise(executor) {
    // 添加属性
    this.promiseStatus = "pending";
    this.promiseResult = null;
    // 声明属性
    this.callback = [];
    // 保存实例对象的 this 的值
    const self = this;  // 一般用 self  _this that
    // resolve 函数
    function resolve(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'fulfiied';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onResolved(data);
        });
    }

    // reject 函数
    function reject(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'rejected';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onRejected(data);
        });
    }
    try {
        // 同步调用 【执行器函数】
        executor(resolve, reject);
    } catch (error) {
        reject(error);
    }
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
    const self = this;
    // 判断 回调函数参数
    if (typeof onRejected !== 'function') {
        onRejected = reason => {
            throw reason;
        }
    }
    if (typeof onResolved !== 'function') {
        onResolved = value => value
    }
    return new Promise((resolve, reject) => {
        // 重复代码太多,封装函数
        function callback(type) {
            try {
                // 获取回调函数的执行结果
                let result = type(self.promiseResult);
                if (result instanceof Promise) {
                    // 如果是一个promise
                    result.then((v) => {
                        resolve(v);
                    }, (r) => {
                        reject(r);
                    })
                } else {
                    // 结果的状态为 【成功】
                    resolve(result);
                }
            } catch (error) {
                reject(error)
            }
        }
        // 调用回调函数  根据对象的状态判断
        if (this.promiseStatus === "fulfiied") {
            callback(onResolved);
        }
        if (this.promiseStatus === "rejected") {
            callback(onRejected);
        }
        // 状态三种,判断为pending的时候
        if (this.promiseStatus === "pending") {
            // 保存回调函数
            this.callback.push({
                onResolved: function () {
                    callback(onResolved);
                },
                onRejected: function () {
                    callback(onRejected);
                },
            })
        }
    })
}

// 添加catch方法
Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected);
}

// 添加 resolve 方法
Promise.resolve = function (value) {
    // 返回 promise 对象
    return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
            value.then((v) => {
                resolve(v);
            }, (r) => {
                reject(r);
            })
        } else {
            resolve(value);
        }
    })
}

// 添加 reject 方法
Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
        reject(reason);
    })
}

2.14 Promise.all 封装

只要一个失败就返回一个失败的promise对象,状态和值为失败的promise的状态和值。

循环遍历执行每一个promise对象的then,成功回调就将值放在数组对应顺序下。

成功的数和传入的数组长度一致时,就证明结束。

// 初始化搭建
function Promise(executor) {
    // 添加属性
    this.promiseStatus = "pending";
    this.promiseResult = null;
    // 声明属性
    this.callback = [];
    // 保存实例对象的 this 的值
    const self = this;  // 一般用 self  _this that
    // resolve 函数
    function resolve(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'fulfiied';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onResolved(data);
        });
    }

    // reject 函数
    function reject(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'rejected';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onRejected(data);
        });
    }
    try {
        // 同步调用 【执行器函数】
        executor(resolve, reject);
    } catch (error) {
        reject(error);
    }
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
    const self = this;
    // 判断 回调函数参数
    if (typeof onRejected !== 'function') {
        onRejected = reason => {
            throw reason;
        }
    }
    if (typeof onResolved !== 'function') {
        onResolved = value => value
    }
    return new Promise((resolve, reject) => {
        // 重复代码太多,封装函数
        function callback(type) {
            try {
                // 获取回调函数的执行结果
                let result = type(self.promiseResult);
                if (result instanceof Promise) {
                    // 如果是一个promise
                    result.then((v) => {
                        resolve(v);
                    }, (r) => {
                        reject(r);
                    })
                } else {
                    // 结果的状态为 【成功】
                    resolve(result);
                }
            } catch (error) {
                reject(error)
            }
        }
        // 调用回调函数  根据对象的状态判断
        if (this.promiseStatus === "fulfiied") {
            callback(onResolved);
        }
        if (this.promiseStatus === "rejected") {
            callback(onRejected);
        }
        // 状态三种,判断为pending的时候
        if (this.promiseStatus === "pending") {
            // 保存回调函数
            this.callback.push({
                onResolved: function () {
                    callback(onResolved);
                },
                onRejected: function () {
                    callback(onRejected);
                },
            })
        }
    })
}

// 添加catch方法
Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected);
}

// 添加 resolve 方法
Promise.resolve = function (value) {
    // 返回 promise 对象
    return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
            value.then((v) => {
                resolve(v);
            }, (r) => {
                reject(r);
            })
        } else {
            resolve(value);
        }
    })
}

// 添加 reject 方法
Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
        reject(reason);
    })
}

// 添加 all 方法
Promise.all = function (promises) {
    return new Promise((resolve, reject) => {
        // 声明变量
        let count = 0;
        let arr = [];
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(v => {
                // 得知对象的状态是成功
                // 每个promise对象都成功
                count++;
                // 将当前promise对象成功的结果,存入数组
                // 并且需要按照顺序存入数组
                arr[i] = v;
                // 判断
                if (count === promises.length) {
                    // 修改状态
                    resolve(arr);
                }
            }, r => {
                reject(r);
            })
        }
    })
}

2.15 Promise.race 封装

哪个第一个返回,哪个就是结果。

// 初始化搭建
function Promise(executor) {
    // 添加属性
    this.promiseStatus = "pending";
    this.promiseResult = null;
    // 声明属性
    this.callback = [];
    // 保存实例对象的 this 的值
    const self = this;  // 一般用 self  _this that
    // resolve 函数
    function resolve(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'fulfiied';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onResolved(data);
        });
    }

    // reject 函数
    function reject(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'rejected';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        self.callback.forEach(item => {
            item.onRejected(data);
        });
    }
    try {
        // 同步调用 【执行器函数】
        executor(resolve, reject);
    } catch (error) {
        reject(error);
    }
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
    const self = this;
    // 判断 回调函数参数
    if (typeof onRejected !== 'function') {
        onRejected = reason => {
            throw reason;
        }
    }
    if (typeof onResolved !== 'function') {
        onResolved = value => value
    }
    return new Promise((resolve, reject) => {
        // 重复代码太多,封装函数
        function callback(type) {
            try {
                // 获取回调函数的执行结果
                let result = type(self.promiseResult);
                if (result instanceof Promise) {
                    // 如果是一个promise
                    result.then((v) => {
                        resolve(v);
                    }, (r) => {
                        reject(r);
                    })
                } else {
                    // 结果的状态为 【成功】
                    resolve(result);
                }
            } catch (error) {
                reject(error)
            }
        }
        // 调用回调函数  根据对象的状态判断
        if (this.promiseStatus === "fulfiied") {
            callback(onResolved);
        }
        if (this.promiseStatus === "rejected") {
            callback(onRejected);
        }
        // 状态三种,判断为pending的时候
        if (this.promiseStatus === "pending") {
            // 保存回调函数
            this.callback.push({
                onResolved: function () {
                    callback(onResolved);
                },
                onRejected: function () {
                    callback(onRejected);
                },
            })
        }
    })
}

// 添加catch方法
Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected);
}

// 添加 resolve 方法
Promise.resolve = function (value) {
    // 返回 promise 对象
    return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
            value.then((v) => {
                resolve(v);
            }, (r) => {
                reject(r);
            })
        } else {
            resolve(value);
        }
    })
}

// 添加 reject 方法
Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
        reject(reason);
    })
}

// 添加 all 方法
Promise.all = function (promises) {
    return new Promise((resolve, reject) => {
        // 声明变量
        let count = 0;
        let arr = [];
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(v => {
                // 得知对象的状态是成功
                // 每个promise对象都成功
                count++;
                // 将当前promise对象成功的结果,存入数组
                // 并且需要按照顺序存入数组
                arr[i] = v;
                // 判断
                if (count === promises.length) {
                    // 修改状态
                    resolve(arr);
                }
            }, r => {
                reject(r);
            })
        }
    })
}

// 添加 race 方法
Promise.race = function (promises) {
    return new Promise((resolve, reject) => {
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(v => {
                resolve(v);
            }, r => {
                reject(r)
            })
        }
    })
}

2.16 回调函数 异步调用

目前情况下,回调函数是同步执行的。按照正常的方式,then是微任务,需要先等待,同步任务执行完之后,才会执行。 

2.16.1 完整版1.0 

// 初始化搭建
function Promise(executor) {
    // 添加属性
    this.promiseStatus = "pending";
    this.promiseResult = null;
    // 声明属性
    this.callback = [];
    // 保存实例对象的 this 的值
    const self = this;  // 一般用 self  _this that
    // resolve 函数
    function resolve(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'fulfiied';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        setTimeout(() => {
            self.callback.forEach(item => {
                item.onResolved(data);
            });
        });
    }

    // reject 函数
    function reject(data) {
        // 判断状态,只能修改一次,即不为pending,就不能执行。
        if (self.promiseStatus !== "pending") { return }
        // 1.修改对象的状态(promiseStatus)
        self.promiseStatus = 'rejected';
        // 2.设置对象结果的值(promiseResult)
        self.promiseResult = data;
        // 调用成功的回调函数
        setTimeout(() => {
            self.callback.forEach(item => {
                item.onRejected(data);
            });
        });
    }
    try {
        // 同步调用 【执行器函数】
        executor(resolve, reject);
    } catch (error) {
        reject(error);
    }
}

// 添加then方法
Promise.prototype.then = function (onResolved, onRejected) {
    const self = this;
    // 判断 回调函数参数
    if (typeof onRejected !== 'function') {
        onRejected = reason => {
            throw reason;
        }
    }
    if (typeof onResolved !== 'function') {
        onResolved = value => value
    }
    return new Promise((resolve, reject) => {
        // 重复代码太多,封装函数
        function callback(type) {
            try {
                // 获取回调函数的执行结果
                let result = type(self.promiseResult);
                if (result instanceof Promise) {
                    // 如果是一个promise
                    result.then((v) => {
                        resolve(v);
                    }, (r) => {
                        reject(r);
                    })
                } else {
                    // 结果的状态为 【成功】
                    resolve(result);
                }
            } catch (error) {
                reject(error)
            }
        }
        // 调用回调函数  根据对象的状态判断
        if (this.promiseStatus === "fulfiied") {
            setTimeout(() => {
                callback(onResolved)
            });
        }
        if (this.promiseStatus === "rejected") {
            setTimeout(() => {
                callback(onRejected)
            });
        }
        // 状态三种,判断为pending的时候
        if (this.promiseStatus === "pending") {
            // 保存回调函数
            this.callback.push({
                onResolved: function () {
                    callback(onResolved);
                },
                onRejected: function () {
                    callback(onRejected);
                },
            })
        }
    })
}

// 添加catch方法
Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected);
}

// 添加 resolve 方法
Promise.resolve = function (value) {
    // 返回 promise 对象
    return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
            value.then((v) => {
                resolve(v);
            }, (r) => {
                reject(r);
            })
        } else {
            resolve(value);
        }
    })
}

// 添加 reject 方法
Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
        reject(reason);
    })
}

// 添加 all 方法
Promise.all = function (promises) {
    return new Promise((resolve, reject) => {
        // 声明变量
        let count = 0;
        let arr = [];
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(v => {
                // 得知对象的状态是成功
                // 每个promise对象都成功
                count++;
                // 将当前promise对象成功的结果,存入数组
                // 并且需要按照顺序存入数组
                arr[i] = v;
                // 判断
                if (count === promises.length) {
                    // 修改状态
                    resolve(arr);
                }
            }, r => {
                reject(r);
            })
        }
    })
}

// 添加 race 方法
Promise.race = function (promises) {
    return new Promise((resolve, reject) => {
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(v => {
                resolve(v);
            }, r => {
                reject(r)
            })
        }
    })
}

2.17 class 封装

使用calss封装。

属于实例对象的方法直接添加到类上。

属于类Promise的方法,需要使用 static ,是属于类的静态方法,属于内部。

2.17.1 完整版2.0 

class Promise {

    // 构造方法
    constructor(executor) {
        // 添加属性
        this.promiseStatus = "pending";
        this.promiseResult = null;
        // 声明属性
        this.callback = [];
        // 保存实例对象的 this 的值
        const self = this;  // 一般用 self  _this that
        // resolve 函数
        function resolve(data) {
            // 判断状态,只能修改一次,即不为pending,就不能执行。
            if (self.promiseStatus !== "pending") { return }
            // 1.修改对象的状态(promiseStatus)
            self.promiseStatus = 'fulfiied';
            // 2.设置对象结果的值(promiseResult)
            self.promiseResult = data;
            // 调用成功的回调函数
            setTimeout(() => {
                self.callback.forEach(item => {
                    item.onResolved(data);
                });
            });
        }

        // reject 函数
        function reject(data) {
            // 判断状态,只能修改一次,即不为pending,就不能执行。
            if (self.promiseStatus !== "pending") { return }
            // 1.修改对象的状态(promiseStatus)
            self.promiseStatus = 'rejected';
            // 2.设置对象结果的值(promiseResult)
            self.promiseResult = data;
            // 调用成功的回调函数
            setTimeout(() => {
                self.callback.forEach(item => {
                    item.onRejected(data);
                });
            });
        }
        try {
            // 同步调用 【执行器函数】
            executor(resolve, reject);
        } catch (error) {
            reject(error);
        }
    }

    // then 方法
    then(onResolved, onRejected) {
        const self = this;
        // 判断 回调函数参数
        if (typeof onRejected !== 'function') {
            onRejected = reason => {
                throw reason;
            }
        }
        if (typeof onResolved !== 'function') {
            onResolved = value => value
        }
        return new Promise((resolve, reject) => {
            // 重复代码太多,封装函数
            function callback(type) {
                try {
                    // 获取回调函数的执行结果
                    let result = type(self.promiseResult);
                    if (result instanceof Promise) {
                        // 如果是一个promise
                        result.then((v) => {
                            resolve(v);
                        }, (r) => {
                            reject(r);
                        })
                    } else {
                        // 结果的状态为 【成功】
                        resolve(result);
                    }
                } catch (error) {
                    reject(error)
                }
            }
            // 调用回调函数  根据对象的状态判断
            if (this.promiseStatus === "fulfiied") {
                setTimeout(() => {
                    callback(onResolved)
                });
            }
            if (this.promiseStatus === "rejected") {
                setTimeout(() => {
                    callback(onRejected)
                });
            }
            // 状态三种,判断为pending的时候
            if (this.promiseStatus === "pending") {
                // 保存回调函数
                this.callback.push({
                    onResolved: function () {
                        callback(onResolved);
                    },
                    onRejected: function () {
                        callback(onRejected);
                    },
                })
            }
        })
    }

    // catch 方法
    catch(onRejected) {
        return this.then(undefined, onRejected);
    }

    // 添加 resolve 方法
    static resolve(value) {
        // 返回 promise 对象
        return new Promise((resolve, reject) => {
            if (value instanceof Promise) {
                value.then((v) => {
                    resolve(v);
                }, (r) => {
                    reject(r);
                })
            } else {
                resolve(value);
            }
        })
    }

    // 添加 reject 方法
    static reject(reason) {
        return new Promise((resolve, reject) => {
            reject(reason);
        })
    }

    // 添加 all 方法
    static all(promises) {
        return new Promise((resolve, reject) => {
            // 声明变量
            let count = 0;
            let arr = [];
            for (let i = 0; i < promises.length; i++) {
                promises[i].then(v => {
                    // 得知对象的状态是成功
                    // 每个promise对象都成功
                    count++;
                    // 将当前promise对象成功的结果,存入数组
                    // 并且需要按照顺序存入数组
                    arr[i] = v;
                    // 判断
                    if (count === promises.length) {
                        // 修改状态
                        resolve(arr);
                    }
                }, r => {
                    reject(r);
                })
            }
        })
    }

    // 添加 race 方法
    static race() {
        return new Promise((resolve, reject) => {
            for (let i = 0; i < promises.length; i++) {
                promises[i].then(v => {
                    resolve(v);
                }, r => {
                    reject(r)
                })
            }
        })
    }
}

三、async 与 await

3.1 mdn 文档

async函数 - JavaScript | MDN

await - JavaScript | MDN

3.2  async 函数

1.函数的返回值为promise对象

2.promise 对象的结果是由 async 函数执行的返回值决定。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>async</title>
</head>

<body>
    <script>
        async function main() {
            // 1.如果返回值是一个非Promise类型的数据
            // return 521;
            // 2.如果返回的是一个 Promise 对象
            // return new Promise((resolve, reject) => {
            //     // resolve('ok');
            //     reject('error');
            // })
            // 3.抛出异常
            // throw 'Oh No'
        }
        let result = main();
        console.log(result);
    </script>
</body>

</html>

3.3 await 表达式

1. await 右侧的表达式一般为 promise 对象,但也可以是其它的值。

2.如果表达式是 promise 对象,await 返回的是 promise 成功的值。

3.如果表达式是其他的值,直接将此值作为await的返回值。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>await</title>
</head>

<body>
    <script>
        async function main() {
            let p = new Promise((resolve, reject) => {
                // resolve('ok');
                reject('error');
            })

            // 1.右侧为promise的情况
            // let res = await p;
            // 2.右侧为其他类型的数据
            let res2 = await 20;
            // 3.如果promise失败的状态
            try {
                let res2 = await p;
            } catch (error) {
                console.log(error); // error
            }
            // console.log(res); // ok
            console.log(res2);  //20
        }
        main();
    </script>
</body>

</html>

3.4 注意

1. await 必须写在 async 函数中,但 async 函数中可以么有 await

2.如果await的promise 失败了,就会抛出异常,需要通过 try .... catch 捕获处理。

3.5 案例

3.5.1nodejs  获取文件内容

const fs = require('fs');

// 之前写法 回调函数的方式
// fs.readFile('./file/1.html', (err, data1) => {
//     if (err) throw err;
//     fs.readFile('./file/2.html', (err, data2) => {
//         if (err) throw err;
//         fs.readFile('./file/3.html', (err, data3) => {
//             if (err) throw err;
//             console.log(data1 + data2 + data3);
//         })
//     })
// })

// async 与 await
const util = require('util');
// util.promisify(fs.readFile) 将方法返回值为一个promise
const mineReadFile = util.promisify(fs.readFile);

async function main() {
    try {
        let data1 = await mineReadFile('./file/1.html');
        let data2 = await mineReadFile('./file/2.html');
        let data3 = await mineReadFile('./file/3.html');
        console.log(data1 + data2 + data3);
    } catch (error) {
        console.log(error);
    }
}
main();

3.5.2 async与await结合发送AJAX

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>4-async与await结合发送AJAX</title>
</head>

<body>
    <button id="btn">获取段子</button>
    <script>
        function sendAJAX(url) {
            return new Promise((resolve, reject) => {
                // 1.创建对象
                const xhr = new XMLHttpRequest();
                // 指定返回的数据格式
                xhr.responseType = 'json';
                // 2.初始化
                xhr.open('GET', url);
                // 3.发送
                xhr.send();
                // 4.处理响应结果
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        if (xhr.status >= 200 & xhr.status < 300) {
                            resolve(xhr.response);
                        } else {
                            reject(xhr.status);
                        }
                    }
                }
            })
        }
        let url = "https://api.apiopen.top/getJoke";
        let btn = document.querySelector('#btn');
        btn.addEventListener('click', async function () {
            let duanzi = await sendAJAX(url);
            console.log(duanzi);
        })
    </script>
</body>

</html>

3.5.3 可以和axios结合使用,axios返回的是一个promise 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值