promise

137 阅读4分钟

promise

ES6语法规范中新增加的内置类,用来处理js中的异步编程的,而我们所谓的promise设计模式,就是基于promise对异步操作进行管理

异步编程中的“回调地狱”

  • Ajax的串行

  • 只有第一个请求成功才能执行第二个,第二个成功才能执行第三个...最后一个请求成功后拿到了每一次请求的所有数据

$.ajax({
url:'/baseInfo',
method:'GET',
data:{
name:'zhanglu'
},
success:result=>{
let scoreId=result.scoreId;
  $.ajax({
        url:'/scoreInfo',
        method:'GET',
        data:{
            id:scoreId
        },
        success:result=>{
            let chinese=result.chinese;

            $.ajax({
                url:'/paiming',
                method:'GET',
                data:{
                    num:chinese
                },
                success:result=>{

                }
            });
        }
    });
}
  });
  • Ajax的并行

  • 三个请求可以同时发送,但是需要等到所有的请求都成功才会做一件事

 let chi=100,
    eng=12,
    math=98;
let chiPai,
    engPai,
    mathPai;
let count=0;
function func(){
    if(count>=3){
        //=>处理自己要做的事情
    }
}

$.ajax({
    url:'/pai?chi='+chi,
    success:result=>{
        chiPai=result;
        count++;
        func();
    }
});
$.ajax({
    url:'/pai?eng='+eng,
    success:result=>{
        engPai=result;
        count++;
        func();
    }
});
$.ajax({
    url:'/pai?math='+math,
    success:result=>{
        mathPai=result;
        count++;
        func();
    }
});

promise的三种状态

new Promise([executor]):第一个执行函数必须传递

[executor 简称EXE]

1.NEW PROMISE的时候就会把EXE执行,创建PROMISE的一个实例(EXE是PROMISE类的一个回调函数,PROMISE内部会把它执行)

2.PROMISE不仅把EXE执行,而且还给EXE传递两个参数(两个参数也是函数类型):

=>resolve函数:它执行代表PROMISE处理的异步事情是成功的,把PROMISE的状态改为fulfilled

=>reject函数:它执行代表PROMISE处理的异步事情是失败的,把PROMISE的状态改为rejected

.EXE函数中放的就是当前要处理的异步操作事情

![PROMISE的基础知识].png](cdn.nlark.com/yuque/0/201… "PROMISE的基础知识].png")

let promiseExamp = new Promise(); 
//=>UncaughtTypeError: Promise resolver undefined is not a function
//new Promise()需要传一个函数,传reolve(成功) reject(失败)的函数

let promiseExamp = new Promise((resolve, reject) => {
    //=>这里一般存放的都是我们即将要处理的异步任务,任务成功我们执行resolve,任务失败我们执行reject
  //(当然写同步的也可以)
    let ran = Math.random();
    setTimeout(() => {
        if (ran < 0.5) {
            reject(ran);
            return;
        }
        resolve(ran);
    }, 1000);
});
promiseExamp.then(result => {
    //=>状态为FULFILLED成功后执行(RESULT:[[PromiseValue]])
    console.log('成功: ' + result);
}, error => {
    //=>状态为REJECTED失败后执行
    console.log('失败: ' + error);
});

try catch解决代码报错,不影响后面代码继续执行

 console.log(a); //=>Uncaught ReferenceError: a is not defined
        let b = 10;
        console.log(b); */

    //=>在JS中当前行代码报错,会中断主线程的渲染(下面代码将不再行)
    // throw new Error(''):手动抛出一个异常错误,目的就是让后代码不再执行
    // 如果上面代码报错,不想让期影响后面的代码,我们需要做异常获:try catch finally

    /* try {
        console.log(a);
    } catch (e) {
        //=>错误信息
        // console.log(e.message);
    }
    let b = 10;
    console.log(b);

promise then设置成功或者失败后执行的方法

   * Promise.prototype
     *    then:设置成功或者失败后执行的方法(成功或者失败都可以设置,也可以只设置一个)
     *       pro.then([success],[error])
     *       pro.then([success])
     *       pro.then(null,[error])
     *    catch:设置失败后执行的方法
     *    finally:设置不论成功还是失败都会执行的方法(一般不用)
    /* let promiseExamp = new Promise((resolve, reject) => {
        setTimeout(() => {
            let ran = Math.random();
            ran < 0.5 ? reject(ran) : resolve(ran);
        }, 1000);
    });
    promiseExamp.then(result => {
        console.log('成功: ' + result);
    });
    promiseExamp.catch(error => {
        console.log('失败: ' + error);
    });
    promiseExamp.finally(x => {
        console.log('哈哈');
    });

promise的then的链式写法

执行then/catch/finally返回的结果是一个全新的promise实例,所以可以链式写下去,下一个then中哪一个方会被执行,由上一个then中的某个方法执行的结果来决定

1.这次执行哪一个方法,看上一个promise执行的状态是否出错和返回结果

2.上一个THEN中某个方法的返回值会传递给下一个THEN的某个方法中

new Promise((resolve, reject) => {
            // resolve(100); //=>把第一个PROMISE实例的VALUE值改为100/-100
            reject(-100);
        }).then(result => {
            console.log(result);
            return result * 10; //=>THEN中RETURN的结果相当于把当前这个新的PROMISE实例中的VALUE值
  改为返回值
        }, err => {
            console.log(err);
            return err / 10;
        }).then(A => {
            console.log('A:' + A);
        }, B => {
            console.log('B:' + B);
        }).then(C => {

        }, D => {

        });

如果当前PROMISE实例的状态确定后,都会到对应的THEN中找方法,如果THEN中没有对应的这个方法,则会向下顺延

THEN(onFulfilled)  THEN(null,onRejected)  
         new Promise((resolve, reject) => {
            reject(-100);
        }).then(A => {
            console.log(A);
            return A * 10;
        }).catch(B => {
            console.log(B); //=>-100
            return B * 10;
        }); 

-------------------------------------------------------------------------------------
         new Promise((resolve, reject) => {
            resolve(100);
        }).then(A => {
            console.log(AAAAA); //=>执行报错,让.THEN创建的PROMISE实例变为失败状态,
  并且把报错的原因修改此PROMISEVALUEreturn A * 10;
        }).catch(B => {
            console.log(B); //=>ReferenceError: AAAAA is not defined
            return '@';
        }).then(C => {
            console.log(C); //=>'@'
        });
--------------------------------------------------------------------------------------
 new Promise((resolve, reject) => {
            resolve();
        }).then().catch(x => {
            console.log(1);
        }).then(x => {
            console.log(2); //=>OK
        }).then(x => {
            console.log(3); //=>OK
        }).catch(x => {
            console.log(4);
        }).then(x => {
            console.log('AAA'); //=>OK
            console.log(AAA); //=>报错
        }).catch().then(null, x => {
            console.log(5); //=>OK
        });
------------------------------------------------------------------------------------
let pro1 = new Promise((resolve, reject) => {
            setTimeout(() => {
                let ran = Math.random();
                ran < 0.5 ? reject(ran) : resolve(ran);
            }, 1000);
        });
        let pro2 = pro1.then(result => {
            console.log(`PRO1:SUCCESS`);
        }, error => {
            console.log(`PRO1:ERROR`)
        });

        let pro3 = pro2.then(result => {
            console.log(`PRO1:SUCCESS`);
        }, error => {
            console.log(`PRO1:ERROR`)
        });

解决Ajax回调地狱问题

function queryBase() {
            return new Promise(resolve => {
                $.ajax({
                    url: '/baseInfo?name=zhanglu',
                    success: result => {
                        resolve(result);
                    }
                });
            });
        }

        function queryScore(scoreId) {
            return new Promise(resolve => {
                $.ajax({
                    url: '/score?id=' + scoreId,
                    success: result => {
                        resolve(result);
                    }
                });
            });
        }

        function queryChinese(chinese) {
            return new Promise(resolve => {
                $.ajax({
                    url: '/paiming?chin=' + chinese,
                    success: result => {
                        resolve(result);
                    }
                });
            });
        }
方法一:
queryBase().then(baseInfo => {
            let scoreId = baseInfo.scoreId;
            //=>THEN方法中如果返回的是一个PROMISE实例,则当前返回实例的成功或者失败状态,
  影响着下一个THEN中哪个方法会被触发执行;如果返回的是非PROMISE实例,则看当前方法执行是否报错,
  来决定下一个THEN中哪个方法执行;
            return queryScore(scoreId);
        }).then(scoreInfo => {
            let chinese = scoreInfo.chinese;
            return queryChinese(chinese);
        }).then(pai => {
            console.log('排名是:' + pai);
        }); */
方法二:
        /* queryBase().then(baseInfo => queryScore(baseInfo.scoreId))
            .then(scoreInfo => queryChinese(scoreInfo.chinese))
            .then(pai => {
                console.log('排名是:' + pai);
            }); */
方法三:
        /* async function func() {
            let baseInfo = await queryBase();
            let scoreInfo = await queryScore(baseInfo.scoreId);
            let pai = await queryChinese(scoreInfo.chinese);
            //....
        }
        func();

解决AJAX并行

function ajax1() {
            return new Promise(resolve => {
                $.ajax({
                    url: '/api1',
                    success: resolve
                });
            });
        }

        function ajax2() {
            return new Promise(resolve => {
                $.ajax({
                    url: '/api2',
                    success: resolve
                });
            });
        }

        function ajax3() {
            return new Promise(resolve => {
                $.ajax({
                    url: '/api3',
                    success: resolve
                });
            });
        }

promise all

Promise.all([promise1,promise2,...]):ALL中存放的是多个PROMISE实例(每一个实例管理者一个异步操作),执行ALL方法返回的结果是一个新的PROMISE实例"PROA"

//=>当所有PROMISE实例的状态都为Fulfilled的时候(成功),让PROA的状态也变为Fulfilled,并且把所有PROMISE成功获取的结果,存储为成为一个数组(顺序和最开始编写的顺序一致)“result=[result1,result2,...]”,让PROA这个数组的VALUE值等于这个数组

//=>都成功(PROA状态是FUFILLED)才会通知THEN中第一个方法执行,只要有一个失败(PROA状态是REJECTED),就会通知THEN中第二个方法或者CATCH中的方法执行

Promise.all([ajax1(), ajax3(), ajax2()]).then(results => {

//=>results:[result1,result3,result2]

});

promise race

Promise.race([ajax1(), ajax3(), ajax2()]).then(result => {

//=>看哪一个PROMISE状态最先处理完(成功或者失败),以最先处理完的为主

});