promise系列(一)

1.同步回调和异步回调

    <script>
        // 同步回调
        let arr = [1,2,3,4,5];
        //对数组的每一个元素 * 10 返回新数组  forEach filter some every
        let newArr = arr.map(item => {
            // console.log(0);
            return item * 10;
        });


        // 异步回调 promise 回调 $.get(url, data, callback)  fs模块 readFile  readdir 
        setTimeout(() => {
            console.log(0);
        }, 1000);

        console.log(1);


    </script>

 

2.错误类型

<script>
    /**
     *  1.    Error: 所有错误的父类型
        2.    ReferenceError: 引用的变量不存在
        3.    TypeError: 数据类型不正确的错误
        4.    RangeError: 数据值不在其所允许的范围内
        5.    SyntaxError: 语法错误
     */

    // ReferenceError  引用错误
    //  console.log(abc);

    // TypeError 类型错误
    // let obj = {};
    // obj();

    // RangeError 范围
    // let arr = new Array(-1);//长度
    // console.log(arr);

    // SyntaxError 语法错误
    // abcxxx(xxxxa'*9s);


</script>

 

3.try...catch 处理错误

   <script>
        /**
         * 语法固定 try...catch   try 尝试的意思  catch 捕获
         * 1. try catch捕获到错误之后, 后续代码可以继续执行
         * 2. catch 可以将错误信息捕获到. e 是一个对象, 有message和stack两个属性
         * 3. 抛出错误之后, 在后续的 try 里面的代码不会执行
         * 4. try 不能捕获语法错误. 其他三种类型错误可以捕获.
         * 5. 允许使用 throw 手动的抛出错误
         * 6. 抛出任意类型的数据
         */

        try {
            // console.log(a;//不能捕获到语法错误
            let a = 100;
            let b = 0;
            if(b === 0) {
                //手动抛出错误对象
                // throw new Error('除数不能为 0');
                throw "除数不能为 0 ";
            }
            let result = a / b;
            console.log("lalala");
        } catch (e) {
            console.log(e);
            console.log(e.message);
            console.log(e.stack);
            //处理错误的方式 
            //1. 写入日志文件
            //2. 错误提醒
        }

        console.log('ok');



    </script>

同步代码和异步代码处理错误

 <script>
        // 同步代码抛出错误  => 可以捕获
        // function fn() {
        //     console.log(a);
        // }

        // try {
        //     fn(); //非手动捕获
        // } catch (e) {
        //     console.log(e.message);
        // }


        // 异步代码抛出错误  => 不能这样捕获
        // function fn() {
        //     setTimeout(() => {
        //         console.log(a);
        //     }, 1000)
        // }
        // try {
        //     fn();
        // } catch (e) {
        //     console.log(e.message);
        // }
        // console.log('test');

        //异步代码捕获错误的方式
        // function fn() {
        //     setTimeout(() => {
        //         try {
        //             console.log(a);
        //         } catch (e) {
        //             console.log(e.message);
        //         }
        //     }, 1000)
        // }
        // fn();

    </script>

 

Promise基础使用

<script>
    // 2s后 随机生成一个数字  
    // 如果是偶数则成功(弹框数字,中奖啦), 
    // 如果是奇数失败(控制台输出数字)

    // setTimeout(() => {
    //     //获取时间戳
    //     let n = Date.now();
    //     //
    //     if(n % 2=== 0){
    //         //成功  值
    //         alert(n + '中奖啦! 中奖啦! 笔记本和台式机有戏啦!!');
    //     }else{
    //         //失败  值
    //         console.log(n, "下次再接再厉!!");
    //     }
    // }, 2000);

    //Promise 实现
    // let a = new Person("xiaohigh");
    //成功和失败的值, p 对象出了有状态属性(status), 还有一个值的属性(value)
    let p = new Promise(function(resolve, reject){
        //定时器
        setTimeout(() => {
            let n = Date.now();
            if(n % 2 === 0){
                //成功
                resolve(n);
            }else{
                //失败
                reject(n);
            }
        }, 2000)
    });

    // 形参的潜规则名称 value 与 reason
    p.then(function(value){
        alert("中奖啦!! oh year"+n);
    }, function(reason){
        console.log("再接再厉"+n);
    });


</script>

2

//读取一个文件内容  ./resource/1.html
const fs = require("fs");

// fs.readFile("./resource/1.html", (err, data) => {
//     if(err){
//         console.log(err);
//         return;
//     }
//     console.log(data.toString());
// });

//Promise 的方式
let p = new Promise((resolve, reject) => {
    fs.readFile("./resource/1-33.html", (err, data) => {
        //判断是否出现错误
        if(err) reject(err);
        resolve(data);
    });
});

//then 方法处理成功或失败的值
p.then((value) =>{
    console.log(value.toString());
}, (reason)=>{
    console.error(reason.code);
});

3

//读取 1.html 和 2.html 合并输出到控制台
const fs = require("fs");

//回调函数的形式处理,回调地狱,特点,外层的函数的结果是内层函数的条件
// fs.readFile("./resource/1.html", (err, data1)=>{
//     if(err) throw err;// 直接抛出错误, 如果这里抛出错误, 则代码会停止
//     fs.readFile("./resource/2.html", (err, data2) => {
//         if(err) throw err;
//         fs.readFile("./resource/3.html", (err, data3)=>{
//             if(err) throw err;
//             console.log(data1 + data2 + data3);
//         })
//     });
// });

//Promise 形式
let p = new Promise((resolve, reject) => {
    //读取 1.html 文件内容
    fs.readFile("./resource/1.html", (err, data) => {
        if (err) reject(err);
        resolve(data);
    });
});

//第二个文件读取 value 为 1.html 的文件内容
//p2为返回的新的promise实例化对象
let p2 = p.then(value => {  //value为1.html的内容,//value是buffer类型数据
    //返回一个 新的Promise 对象
    return new Promise((resolve, reject) => {
        fs.readFile("./resource/2.html", (err, data) => {
            if(err) reject(err);
            resolve(value + data);
        });
    });
}, reason => {

});

//读取 3.html 的文件内容
let p3 = p2.then(value => {  //value 为p2中正确状态的值,1.html和2.html的数据
    //value是字符串类型数据,buffer类型相加是字符串类型
    return new Promise((resolve, reject)=>{
        fs.readFile("./resource/3.html", (err, data)=>{
            if(err) reject(err);
            resolve(value + data);
        });
    })
}, reason => {

});

p3.then(value => {  //value 为p3中正确状态的值,1.html和2.html和3.html的数据
    console.log(value); //value是字符串类型数据
},reason => {

})

4

//读取 1.html 和 2.html 3.html 合并输出到控制台
const fs = require("fs");

//Promise 形式
let p1 = new Promise((resolve, reject) => {
    //读取 1.html 文件内容
    fs.readFile("./resource/1.html", (err, data) => {
        if (err) reject(err);
        resolve(data.toString());
    });
});
let p2 = new Promise((resolve, reject)=>{
    //读取 2.html 文件内容
    fs.readFile("./resource/2.html", (err, data) => {
        if (err) reject(err);
        // console.log('dg')  //失败的promise,还是会向下执行代码
        resolve(data.toString());
    });
});
let p3 = new Promise((resolve, reject)=>{
    //读取 3.html 文件内容
    fs.readFile("./resource/3.html", (err, data) => {
        if (err) reject(err);
        resolve(data.toString());
    });
});

//只要有一个状态是失败的,p就是失败的promise
let p = Promise.all([p1, p2, p3]);

p.then(value => {
    // console.log(value)  //value此时是数组,是偏p1,p2,p3的值得累加

     // join()方法将一个数组(或一个类数组对象)的所有元素根据传入的参数连接成一个字符串,并返回这个字符串。
    // 参数:

    // 指定一个字符串来分割数组(类数组)的每个元素

    // 如果省略(),数组元素默认以逗号分隔。默认为","

    // 如果为(""),则表示所有元素之间不存在任何字符
    console.log(value.join(''));
},reason=>{
    console.log(reason)
});

5.promise封装ajax请求

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Promise封装AJAX请求</title>
    <script crossorigin="anonymous" src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
</head>

<body>
    <button id="btn">点击发送 AJAX 请求</button>
    <script>
        // $.get('/server', {}, function(){
        // })
        /*
            封装一个函数 promiseAJAX  只实现 GET 请求
            用来发送 AJAX 请求
            返回 Promise 对象
        */
            //method = "GET", 函数默认参数,promiseAJAX()就是promise对象
        function promiseAJAX({ url,data={name:'maco'}, method = "GET" }) {  //对象解构
            // console.log(url)
            // console.log(method)
            // console.log(data)
              //返回promise实例对象
            return new Promise((resolve, reject) => {
                // 创建ajax实例对象
                let x = new XMLHttpRequest();
                //初始化
                x.open(method, url);
                //发送
                x.send();
                //绑定事件, 处理响应结果
                //只有ajax的状态改变了,才会触发该事件onreadystatechange 
                x.onreadystatechange = function () {// 1->2 2->3  3-> 4
                    //只有状态为 4 的时候, 才能对 Promise 对象状态进行设置
                    if (x.readyState === 4) {
                        //请求成功 2xx 都标识成功   3 重定向   4 客户端错误  5 服务端错误
                        if (x.status >= 200 && x.status < 300) {
                            //成功的话, 将promise对象的状态设置为成功, 并将响应体设置为 promise 对象成功的值
                            resolve(x.response);
                        } else {
                            //失败的话
                            reject(x.status);
                        }
                    }

                }
            });
        }

        btn.onclick = function () {
            //原生ajax-cors跨域,服务器的响应头设置了可跨域
            let url = 'https://www.tianqiapi.com/api/?version=v1&city=%E5%8C%97%E4%BA%AC&appid=23941491&appsecret=TXoD5e8P';
            promiseAJAX({
                url: url
            }).then(value => {
                // 将字符窜转换成对象
                let data=JSON.parse(value)
                console.log(data);
            });
        }


    </script>
</body>

</html>

6.异步API的promsie形态

/*
    封装一个函数 mineReadFile , 读取文件并返回一个 promise 对象
 */
const fs = require("fs");

function mineReadFile(path) {
    //返回promise对象
    return new Promise((resolve, reject)=>{
        //使用 fs 模块读取文件内容
        fs.readFile(path, (err, data) => {
            //如果失败 则修改promise对象状态为失败
            if(err) reject(err);
            // 如果成功, 则修改promise对象状态为成功
            resolve(data);
        })
    });
}

mineReadFile('./resource/xxx.html').then(value => {
    console.log(value.toString());
}, reason => {
    console.log(reason.code);
});

7.promise的API

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Promise的API</title>
</head>

<body>

    <script>
        //  function Promise(executor){

        //  }
        /**
         * 1. Promise 的实例化接收一个 函数类型的参数( 执行器函数 )
         * 2. resolve和 reject 两个形参类型都是 函数.
         * 3. 执行器函数是一个同步的回调函数
         */
        // 1. 执行器函数式同步调用的,但是里头的异步任务是不同步的
        // let p =new Promise((resolve, reject) => {
        //     //同步调用
        //     console.log(111);
        //     //异步调用
        //     setTimeout(()=>{
        //         console.log(333);
        //         // reject("失败的数据");
        //     }, 1000);
        // });
        // console.log(222);
        // 执行顺序, 输出,111, 222, 333

        // 2. Promise.prototype.then
        //成功的回调 onResolved  on 当...时候  resolved 已解决
        //失败的回调 onRejected                rejected 拒绝了的 失败了
        // then方法返回的是一个promise对象,后面还可以加.
        // p.then(value=>{

        // }, reason=>{

        // }).then(value=>{

        // }).then(value=> {

        // });

        // 3. Promise.prototype.catch  实例对象上可以使用 catch 方法
        // p.catch(reason => {
        //     console.error(reason);
        // });

        // 4. Promise.resolve resolve 是一个方法, 返回是一个 Promise 对象

        // 4-1 参数如果为非 Promise 类型的数据, 则返回的 Promise 对象为成功的状态
         // let p10=Promise.resolve('hrllow')
        // console.log(p10)  //Promise { 'hrllow' }
        // p10.then((value)=>{ 
        //     console.log(value)   //hrllow
        // })


        // 4-2 参数如果是成功的 Promise, 则返回的 Promise 对象结果状态也为成功, 
        // 并且返回的成功的promise的值, 为传入参数的成功的值
        // let p1 = new Promise((resolve, reject)=>{
        //     resolve('成功的数据');
        // });
        // let p3 = Promise.resolve(p1); //Promise { '成功的数据' }
        // p3.then(value=>{
        //     console.log(value)  //成功的数据
        // })


        // 4-3 如果参数为失败的 Promise, 则返回的是失败的 Promise 对象
        // 返回的值,报错
        let p11 = new Promise((resolve, reject) => {
            reject("失败的数据111");
        });
        let p4 = Promise.resolve(p11);
        console.log(p4); //Promise { <rejected> '失败的数据111' }
        // p4.then(value=>{
        //     console.log(value)  // Uncaught (in promise) 失败的数据111
        // })

        p4.catch(reason=>{
            console.log(reason)  //失败的数据111
        })
        


        // 5-1. Promise.reject 参数为成功的promise对象,返回失败的 Promise 对象, 返回的值是一个失败原因的对象
        
        // let p0 = new Promise((resolve, reject)=>{
        //     resolve('成功的数据');
        // });
        // let p2 = Promise.reject(p0);
        // console.log(p2);  //Promise {<rejected>: Promise}
        // p2.catch( reason=>{
        //     console.log(reason) //Promise {<resolved>: "成功的数据"}
        // })


        // 5-2. Promise.reject 参数为失败的promise对象,返回失败的 Promise 对象, 返回的值是一个失败原因的对象
        // let p20 = new Promise((resolve, reject)=>{
        //     reject('成功的数据');
        // });
        // let p21 = Promise.reject(p20);
        // console.log(p21);  //Promise {<rejected>: Promise}
        // p21.catch( reason=>{
        //     console.log(reason) //Promise {<rejected>: "成功的数据"}
        // })

        //5-3,Promise.reject 参数为非promise数据,返回失败的 Promise 对象, 返回的值为失败的值
        // let p6=Promise.reject('ABN')
        // console.log(p6)  //Promise {<rejected>: "ABN"}
        // p6.catch(reason=>{
        //     console.log(reason)  //ABN
        // })
      

        // 6. Promise.all, 
        // let one = new Promise((resolve, reject) => {
        //     // reject('数据库用户的数据');
        //     // resolve('数据库用户的数据');

        
        // });
        // let two = Promise.resolve("订单数据");
        // let three = Promise.resolve("商品数据");

        // Promise.all函数的数组参数的promise如果都是成功的状态,那么p1也是成功的promise,而他的返回值是数组
        // 如果有一个参数是失败的promise,那么p1就是失败的promise,
        // let p1 = Promise.all([one, two, three]); 
        // console.log(p1)  //Promise {resolved}
        // p1.then(value=>{
        //     console.log(value) //[ '数据库用户的数据', '订单数据', '商品数据' ]
        // })


        // 7. Promise.race race 赛跑的意思,
        let one = new Promise((resolve, reject) => {
            reject('数据库用户的数据');
            //异步调用
            // setTimeout(() => {
            //     reject('数据库用户的数据');
            // }, 1000);
        });
        let two = Promise.reject("订单数据");
        // let two = Promise.resolve("订单数据");
        let three = Promise.resolve("商品数据");

        //Promise.race函数的数组里头的参数,p1的状态初始是pending默认状态,那个promise状态第一个先改变,p1的状态就会跟着改变
        // 返回的值就是那个引起变化的promise的值,偏
        let p1 = Promise.race([one, two, three]);

        console.log(p1);  
        p1.then(value=>{
            console.log(value)
        },reason=>{
            console.log(reason)
        })

    </script>
</body>

</html>

8.如何改变promsie的状态

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>关键问题</title>
</head>

<body>
    <script>
        let p = new Promise((resolve, reject) => {
            //1. resolve  //"pending"状态的promise
            // resolve('数据');  //resolved
            //2. reject
            // reject('错误');   //rejected"
            //3. 抛出错误,会改变promise的状态
            // throw new Error("出错啦!!");   //rejected"
            // throw "出错啦!!";   //"rejected"
            //4. 异步回调 异步回调中抛出错误 不能改变 promise 对象状态
            // 但是里头加入try,catch即可捕获到错误,就能改变promise的状态
            //异步任务
            // setTimeout(()=>{
            //     reject('失败')  //rejected
            // },1000)

            // setTimeout(()=>{
            //     throw '出错了'  // "pending,未改变状态
            // },1000)

            setTimeout(()=>{

                try{
                    throw '出错了' ;
                }catch(e){
                    reject(e)  //"rejected
                }

            },1000)
        })

        console.log(p);

    </script>
</body>

</html>

9、改变状态和与指定回调谁先谁后

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>关键问题</title>
</head>

<body>
    <script>

    // 改变promise状态和指定回调函数谁先谁后?
    // 1.如果promise中有异步任务,那么先调用then()指定里头的回调,然后在改变promise状态,
    // 然后返回改变状态的值。这种居多,因为promise里头就是封装异步任务的。

    // 2.如果promise中有没有异步任务,那么先改变promise状态,然后调用then()指定里头的回调,
    // 然后返回改变状态的值

    //3.then()方法里头的回调函数也是异步任务
    


        let p = new Promise((resolve, reject) => {
            //异步任务
            // setTimeout(() => {
            //     console.log(111);
            //     resolve("OK");
            // }, 2000);
            //同步任务
            console.log(111);
            resolve("OK");
        });

        console.log(222);
        p.then(value => {
            console.log(value);
        })

        console.log(333)
    </script>
</body>

</html>

10.then 方法返回结果特点

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>关键问题</title>
</head>
<body>
<script>
    let p = new Promise((resolve, reject)=>{
        // resolve('成功')
        reject('失败');
    });

    //由then()指定的回调函数执行的结果决定 
    let result = p.then(value => {
        //1. 抛出错误 ,返回的就是reject状态的promise
        // throw "错误!!";  //"rejected"状态的promise

        //2. 返回非 Promise 类型的对象,如果没有return结果,也是resolved状态
        // return 123;  //"resolved状态的promise,

        //3. 返回 Promise 类型的对象
        return new Promise((resolve, reject)=>{
            // 成功的情况
            // resolve("OK");  //resolved状态的promise,值就是result的值
            // 失败的情况 
            reject('Error');  //rejected状态的promise
        });
    }, reason => {
        console.log(reason) //失败
        return 444  //resolved状态的promise,值就是444,没有return结果,也是resolved状态的promise
    });

    console.log(result);
</script>
</body>
</html>

11.then方法链式调用

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>关键问题</title>
</head>

<body>
    <script>
        let p = new Promise((resolve, reject)=>{
            // resolve('000');
            reject('出错')
        });

        let p2= p.then(value => {
            console.log(value);  //000
            return 111;   //返回状态为resolve,值为111的promise
        },reason => {
            console.error(reason);  //出错
            return 222;  ////返回状态为resolve,值为222的promise
        })
        .then(value => {
            console.log(value);  //111  /222
            return 333;  //返回状态为resolve,值为333的promise
        },reason=>{
            console.error(reason) 

        })
        .then(value => {
            console.log(value);  //333
            return 444;  //返回状态为resolve,值444的promise
        });

        console.log(p2)  //Promise {<resolve>},值为444
    </script>
</body>

</html>

 

12.异常穿透
<!doctype html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>关键问题</title>
</head>

<body>
    <script>
        // 如果出现了状态为rejcet的promise,调用then方法,如果没有写明第二个回调函数,会忽略,
        // 直到遇到catch(),才会执行。异常穿透

        let p = new Promise((resolve, reject) => {
            resolve('000');
            // reject('失败ooo');
        });

        p.then(value => {
            console.log(value);
            throw "Error";
        }).then(value => {
            console.log(value);
            return 333;
        }).then(value => {
            console.log(value);
            return 444;
        }).then(value=> {
            console.log(value);
        }).catch(reason => {
            console.log(reason);
        });
    </script>
</body>

</html>

13.中断promise链

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>关键问题</title>
</head>

<body>
    <script>

//     如何当使用promise的then链式调用时, 在中间中断, 不再调用后面的回调函数
//     办法: 在回调函数中返回一个pendding状态的promise对象

        let p = new Promise((resolve, reject) => {
            resolve('000');
            // reject('失败ooo');
        });

        p.then(value => {
            console.log(value);
            return 111;
        }).then(value => {
            console.log(value);
            return 222;
        }).then(value => {
            console.log(value);
            // 在回调函数中返回一个pendding状态的promise对象
            return new Promise((resolve, reject)=>{});
        }).then(value => {
            console.log(value);
        }).catch(reason => {
            console.log(reason);
        });
    </script>
</body>

</html>

 

 

posted @ 2021-03-17 15:44  全情海洋  阅读(116)  评论(0编辑  收藏  举报