promise执行顺序总结

Posted by JackPeng on November 7, 2019
1、	const promise = new Promise((resolve, reject)=>{
		  console.log(1);
		  resolve();
		  console.log(2);
		})
		promise.then(()=>{
		  console.log(4);
		})
		console.log(5);

运行结果是: 1,2,5,4

解释:promise的构造函数是同步执行,promise.then中的函数是异步执行。

2、 	const promise = new Promise((resolve, reject) => {
		  resolve('success1')
		  reject('error')
		  resolve('success2')
		})
		promise
		  .then((res) => {
		    console.log('then: ', res)
		  })
		  .catch((err) => {
		    console.log('catch: ', err)
		  })

运行结果:then: success1

解释:构造函数中的 resolve 或 reject 只有第一次执行有效,多次调用没有任何作用。promise 状态一旦改变则不能再变。 promise 有 3 种状 态: pending、fulfilled 或 rejected。 状态改变只能是 pending->fulfilled 或者 pending-> rejected,状态一旦改变则不能再变。

3、const promise = new Promise((resolve, reject) => {
	  setTimeout(() => {
	    console.log('once')
	    resolve('success')
	  }, 1000)
	})
	
	const start = Date.now()
	promise.then((res) => {
	  console.log(res, Date.now() - start)
	})
	promise.then((res) => {
	  console.log(res, Date.now() - start)
})

运行结果: once success 1005 success 1007

解释:promise 的 .then 或者 .catch 可以被调用多次,但这里 Promise 构造函数只执行一次。或者说 promise 内部状态一经改变,并且有了一个值,那么后续每次调用 .then 或者 .catch 都会直接拿到该值。

4、console.log('start');
	new Promise(function(resolve,reject){
	    setTimeout(function(){    //定时器模拟异步
	        resolve('hello');    //修改promise状态调用then中的第一个函数
	    },2000);
	}).then((value)=>{
	    console.log(value);    //接收resolve传来的值
	    return new Promise(function(resolve){   //该then()返回一个新的promise实例,后面可以继续接then
	        setTimeout(function(){
	            resolve('world');       //修改新promise的状态,去调用then
	        },3000)
	    })  
	}).then((value)=>{
	   console.log(value);
	})

//输出结果: /* 立即输出 start 两秒输出 hello 再三秒 world */

5、上面我们在 then() 函数中返回的是一个新的promise,如果返回的不是一个新的promise会怎样呢?依然是上面的代码,稍作修改。

console.log('start');
new Promise(function(resolve,reject){
    setTimeout(function(){  
        resolve('hello');    
    },2000);
}).then((value)=>{
    console.log(value);  
    (function(){
        return new Promise(function(resolve){   
            setTimeout(function(){
                resolve('world');       
            },3000)
        })  
    })();  
    return false; 
}).then((value)=>{
   console.log(value);
})

/*
    结果:
       立即输出   start
       两秒输出   hello
       三秒输出   false
*/

根据上面的运行结果来看,如果在一个then()中没有返回一个新的promise,则return 什么下一个then就接受什么,在上面的实例代码中return的是false,下一个 then中接受到的value就是false,如果then中没有return,则默认return的是 undefined.

6、then()中包含.then()的嵌套情况 then()的嵌套会先将内部的then()执行完毕再继续执行外部的then();在多个then嵌套时建议将其展开,将then()放在同一级,这样代码更清晰。

console.log('start');
new Promise((resolve,reject)=>{
    setTimeout(function(){
        console.log('step');
        resolve(110);
    },1000)
})
.then((value)=>{
    return new Promise((resolve,reject)=>{
        setTimeout(function(){
            console.log('step1');
            resolve(value);
        },1000)
    })
    .then((value)=>{
        console.log('step 1-1');
        return value;
    })
    .then((value)=>{
        console.log('step 1-2');
        return value;
    })
})
.then((value)=>{
    console.log(value);
    console.log('step 2');
})
/*
 start
 step
 step1
 step 1-1
 step 1-2
 110
 step 2
*/
 
//展开之后的代码
console.log('start');
new Promise((resolve,reject)=>{
    setTimeout(function(){
        console.log('step');
        resolve(110);
    },1000)
})
.then((value)=>{
    return new Promise((resolve,reject)=>{
        setTimeout(function(){
            console.log('step1');
            resolve(value);
        },1000)
    })
})
.then((value)=>{
        console.log('step 1-1');
        return value;
    })
.then((value)=>{
    console.log('step 1-2');
    return value;
})
.then((value)=>{
    console.log(value);
    console.log('step 2');
})

7、catch和then的连用 如果每一步都有可能出现错误,那么就可能出现catch后面接上then的情况。上代码

new Promise((resolve,reject)=>{
    resolve();
})
.then(value=>{
    console.log('done 1');
    throw new Error('done 1 error');
})
.catch(err=>{
    console.log('错误信息1:'+err);
})
.then(value=>{
    console.log('done 2');
})
.catch(err=>{
    console.log('错误信息2:'+err);
})
/*
 done 1
 错误信息1:Error: done 1 error
 done 2
 说明catch后面会继续执行then,catch返回的也是一个promise实例
*/
new Promise((resolve,reject)=>{
    resolve();
})
.then(value=>{
    console.log('done 1');
    throw new Error('done 1 error');
})
.catch(err=>{
    console.log('错误信息1:'+err);
    throw new Error('catch error');
})
.then(value=>{
    console.log('done 2');
})
.catch(err=>{
    console.log('错误信息2:'+err);
})
/*
 done 1
 错误信息1:Error: done 1 error
 错误信息2:Error: catch error
 如果在catch中也抛出了错误,则后面的then的第一个函数不会执行,因为返回的
 promise状态已经为rejected了

8、Promise.all() 将多个Promise批量执行,所有的Promise都完毕之后返回一个新的Promise

1、接收一个数组作为参数
2、数组中可以是Promise实例,也可以是别的值,只有Promise会等待状态的改变
3、所有子Promise完成,则该Promise完成,并且返回值是参数数组中所有Promise实
例的结果组成的数组
4、有任何一个Promise失败,则该Promise失败,返回值是第一个失败的Promise的结果
console.log('here we go');
Promise.all([1,2,3])
    .then(all=>{
        console.log('1: ' + all); 
        return Promise.all([function(){
            console.log('ooxx');
        },'xxoo',false])
    })
    .then(all=>{
        console.log('2: ' + all);
        let p1 = new Promise(resolve=>{
            setTimeout(function(){
                resolve('I\'m p1');
            },1500)
        });
        let p2 = new Promise(resolve=>{
            setTimeout(function(){
                resolve('I\'m p2');
            },2000)
        });
        return Promise.all([p1,p2]);
    })
    .then(all=>{
        console.log('3: '+all);
        let p1 = new Promise((resolve,reject)=>{
            setTimeout(function(){
                resolve('P1');
            },1000)
        })
        let p2 = new Promise((resolve,reject)=>{
            setTimeout(function(){
                reject('P2');
            },3000)
        })
        let p3 = new Promise((resolve,reject)=>{
            setTimeout(function(){
                reject('P3');
            },2000)
        })
        return Promise.all([p1,p2,p3]);
    })
    .then(all=>{
        console.log('all: ' + all);
    })
    .catch(err=>{
        console.log('Catch:' + err);
    })
    /*
         here we go
         1: 1,2,3
         2: function(){
            console.log('ooxx');
            },xxoo,false
         3: I'm p1,I'm p2    
         Catch:P3      
         证明了上面的四点。
    */

9、Promise.race() 和Promise.all()差不多,区别就是传入的数组中有一个Promise完成了则整个Promise完成了。

let p1 = new Promise(resolve=>{
    setTimeout(function(){
        resolve('p1');
    },10000);
	})
	let p2 = new Promise(resolve=>{
	    setTimeout(function(){
	        resolve('p2');
	    },1000);
	})
	Promise.race([p1,p2])
	.then((value)=>{
	    console.log(value);
	})
	/*
	    p1     1s之后输出
	    。。    等待十秒后代码才算执行完毕
	*/