J57 promise

128 阅读5分钟

一、什么是promise?

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

  • console.dir(promise)
  • new promise(function(){})

1.异步编程中的回调地狱

  • 1.ajax的串行: 只有第一个请求成功才能执行第二个,第二个成功才能执行第三个,最后一个请求成功后,拿到了每一次请求的所有数据
//
$.ajax({
    url:'/baseInfo',
    method:'GET',
    data:{
        name:'zhangsan'
    },
    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=>{

                    }

                })
            }
        })
    }
})
  • 2.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的executor函数和状态、

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

  • 1.new promise的时候就会吧executor执行,创建promise的一个实例(executor是promise类的一个回调函数,promise内部会吧它执行)
  • 2.promise不仅把executor执行,而且还给executor传递两个参数(两个参数也是函数类型):
    • resolve函数:它执行代表promise处理的异步事情是成功的,把promise的状态改为fulfilled
    • reject函数:它执行代表promise处理的异步事情是失败的,把promise的状态改为reject
  • 3.executor函数中放的就事当前要处理的异步操作事情
let promiseExE=new Promise();//=>Uncaught TypeError: Promise resolver undefined is not a function

let promiseExecutor=new Promise((resolve,reject)=>{
//这里 一般存放的都是我们即将要处理的异步任务,任务成功我们执行resolve,任务失败我们执行reject 当然写同步的也可以

setTimeout(()=>{
    if(Math.random()<0.5){
        reject();
        return;
    }
    resolve();    
},1000)
})

2.Promise的三个状态

  • 1.pending:初始状态(new promise后的状态)
  • 2.fulfilled:成功状态(在executor函数中把resolve执行,就事告知promise当前异步操作的结果是成功的)
  • 3.rejected:失败状态(在executor函数中吧reject执行,就事告知promise当前异步操作的结果是失败的)

3.执行executor

  • 1.执行executor函数,初始状态
let pro=new Promise([executor]);
[[PromiseStatus]]:'pending'
[[PromiseValue]]:undefined
  • 2.把executor函数中异步操作开始执行:设置一个定时器,1000ms后执行定时器方法...等异步操作完成

  • 3.在异步操作完成后,通过执行resolve/reject修改后pro的状态(假设当前案例执行的是resolve) let pro=new Promise([executor]); [[PromiseStatus]]:'fulfilled' [[PromiseValue]]:undefined

  • 4.resolve和reject在执行的时候,我们可以给其传参,传递的参数值会修改pro的value值。 let pro=new Promise([executor]); [[PromiseStatus]]:'resolve' [[PromiseValue]]:'哈哈'

 let promiseExeamp=new Promise((resolve,reject)=>{
        setTimeout(()=>{
            if(Math.random()<0.5){
                reject('呵呵');
                return;
            }
            resolve('哈哈');    
        },1000)
    })

//=>控制台输出dir(promiseExeamp); 结果
// [[PromiseStatus]]:'resolve'
// [[PromiseValue]]:'哈哈'

三、promise中的then和catch

1.then(func1,func2)

  let promiseExeamp=new Promise((resolve,reject)=>{
        setTimeout(()=>{
            let ran=Math.random();
            if(ran<0.5){
                reject(ran);
                return;
            }
            resolve(ran);    
        
    },1000)

});
promiseExeamp.then(result=>{
    //状态为fulfilled成功后执行(result:[PromiseValue])
  console.log('成功:'+result);
},error=>{
    //状态为rejected失败后执行
console.log('失败'+error)
})

2.then(func)

  let promiseExeamp=new Promise((resolve,reject)=>{
        setTimeout(()=>{
            let ran=Math.random();
            if(ran<0.5){
                reject(ran);
                return;
            }
            resolve(ran);    
        
    },1000)

});
promiseExeamp.then(result=>{
    //状态为fulfilled成功后执行(result:[PromiseValue])
  console.log('成功:'+result);
}

3.promise.prototype

  • 1.then:设置成功或失败后执行的方法(成功或者失败都可以设置 也可以设置一个)
    • pro.then([success],[error])
    • pro.then([success])
    • pri.then(null,[error])
  • 2.catch:设置失败后执行的方法
  • 3.finally:设置不论成功还是失败都会执行的方法(一般不用)
  let promiseExeamp=new Promise((resolve,reject)=>{
        setTimeout(()=>{
            let ran=Math.random();
            if(ran<0.5){
                reject(ran);
                return;
            }
            resolve(ran);          
    },1000)  
});

promiseExeamp.then(result=>{
    //状态为fulfilled成功后执行(result:[PromiseValue])
  console.log('成功:'+result);
});

promiseExeamp.catch(error=>{   
  console.log('失败:'+error);
});

promiseExeamp.finally(x=>{
  console.log('哈哈');
});

4.then链

  • 1.then(onResolve,onReject)
  • 2.执行then/catch/finally返回的结果是一个全新的promise实例
let pro1=new Promise((resolve,reject)=>{
        setTimeout(()=>{
            let ran=Math.random();
            ran<0.5?reject(ran):resolve(ran);
        },1000);   
    })
    console.log(pro1);//=>Promise {<pending>}


    let pro2=pro1.then(result=>{

    },error=>{

    });
    console.log(pro2);//=>Promise {<pending>}
    console.log(pro1===pro2);//=>false 

   let pro1=new Promise((resolve,reject)=>{
        setTimeout(()=>{
            let ran=Math.random();
            ran<0.5?reject(ran):resolve(ran);
        },1000);   
    })
    console.log(pro1);//=>Promise {<pending>}


    let pro2=pro1.then(result=>{
       console.log(`PRO1:SUCCESS`);
    },error=>{
       console.log(`PRO1:ERROR`);//=>PRO1:ERROR
    });
    console.log(pro2);//=>Promise {<pending>}
  • 2.执行then/catch/finally返回的结果是一个全新的promise实例,所以可以链式写下去,下一个THEN中那个方式会被执行,由上一个THEN中某个方法执行的结果来决定
 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`); 
    });
    console.log(pro2);//=>Promise {<pending>}

    let pro3=pro2.then(result=>{
        console.log(`PRO1:SUCCESS`); 
    },error=>{
        console.log(`PRO1:ERROR`);
    })
    //随机的结果每次都不一样,所以执行结果也是根据每次随机结果而定
  • 3.上一个THEN中某个方法的返回值会传递给下一个THEN的某个方法中
  //1.失败
     new Promise((resolve,reject)=>{
        //  resolve (100);
         reject(-100);
     }).then(result=>{
         console.log(result);
     },err=>{
         console.log(err);//=>-100
     })

    //2.成功
    new Promise((resolve,reject)=>{ 
            resolve (100);       
        }).then(result=>{
            console.log(result);//=>100
        },err=>{
            console.log(err);
        })

    //3.成功 两个then链
     new Promise((resolve,reject)=>{ 
            resolve (100);       
        }).then(result=>{
            console.log(result);//=>100
        },err=>{
            console.log(err);
        }).then(A=>{
            console.log(A);//=>undefined
        },B=>{
             console.log(B);        
        })

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

        //5.then链可以继续向下写
         new Promise((resolve,reject)=>{ 
            resolve (100);//=>把第一个promise实例value值改为100、-100
            reject(-100);       
        }).then(result=>{
            console.log(result);//=>100
//=>THEN中的return的结果相当于把当前这个新的promise实例中value值改为返回值
            return result *10;
        },err=>{
            console.log(err);
            return result/10;
        }).then(A=>{
            console.log('A:'+A);//=>1000
        },B=>{
             console.log('B:'+B);        
        }).then(C=>{

        },D=>{

        })
  • 4.如果当前promise实例的状态确定后都会到对应的then中找到方法,如果then中没有对应的方法则会向下顺延
//1.失败
    new Promise((resolve,reject)=>{     
      reject(-100);
    }).then(A=>{
        console.log('A:'+A);
        return A*100;
    }).catch(B=>{
        console.log('B:'+B);//=>-100
        return B*10;
    });

       //2.成功
      new Promise((resolve,reject)=>{     
        resolve(100);
        }).then(A=>{
            console.log('A:'+A);//=>100
            return A*100;
        }).catch(B=>{
            console.log('B:'+B);
            return B*10;
        });

      //3. 提示报错
     new Promise((resolve,reject)=>{     
      resolve(100);
    }).then(A=>{
//=>执行报错,让then创建的promise实例变为失败状态,并且把报错的原因修改此promise的value值
        console.log(AAAA);
        return A*100;
    }).catch(B=>{
        console.log('B:'+B);//=>B:ReferenceError: AAAA is not defined
        return '@';
    });

  //4.顺延练习题
    new Promise((resolve,reject)=>{
        resolve();
    }).then(
     //=>没有顺延
    ).catch(x=>{
        console.log(1);
    }).then(x=>{
        console.log(2);//=>2
    }).then(x=>{
        console.log(3);//=>3
    }).catch(x=>{
        console.log(4);
    }).then(x=>{
        console.log(AAA);//=>AAA is not defined
        console.log('AAA');//=>'AAA'
    }).catch().then(null,x=>{
        console.log(5);//=>5
    });

四、promise其它常用方法

  • 1.Promise.all
  • 2.Promise.race
  • 3.Promise.reject
  • 4.Promise.resolve

1.解决AJAX回调地狱

function queryBase() {
			return new Promise(resolve => {
				$.ajax({
					url: '/baseInfo?name=zhangsan',
					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);
					}
				});
			});
		}
          
        //1.写法一
		 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);
		}); 

        //2.写法二
	     queryBase().then(baseInfo => queryScore(baseInfo.scoreId))
			.then(scoreInfo => queryChinese(scoreInfo.chinese))
			.then(pai => {
				console.log('排名是:' + pai);
			}); 

        //3.写法三
	    async function func() {
			let baseInfo = await queryBase();
			let scoreInfo = await queryScore(baseInfo.scoreId);
			let pai = await queryChinese(scoreInfo.chinese);
			//....
		}
		func();

2.解决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([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([ajax1(), ajax3(), ajax2()]).then(result => {
			//=>看哪一个PROMISE状态最先处理完(成功或者失败),以最先处理完的为主
		});