JS - Promise使用

在JavaScript中代码都是单线程执行的,因此JavaScript中所有的网络操作、浏览器事件都必须异步执行。在Promise之前JavaScript处理异步的方式都是回调函数。可以说callback的方式已是深入人心,那Promise又是解决什么问题的呢?看下面一段代码:

$.get('/getList',function(){
	$.get('/getCount',function(){
		$.get('/getDetail',function(){
			//....
		})
	})
})

这段代码就是传统的callback方式处理异步,可以看到刚刚3级嵌套代码层级就已经比较乱了,如果再加上一些逻辑代码那简直是无法直视。这就是我们常说的回调地狱问题。代码可读性低,难以复用。

Promise解决回调地狱

Promise的基本用法

var promise = new Promise((resolve,reject)=>{
	setTimeout(function(){
		//这里异步操作已经执行完了,就可以通过resolve告诉外界可以进行其他操作了
		resolve('ok');
		//reject('no');
	},2000);
})

promise.then(res=>{
	console.log(res); // ok
},err=>{
	console.log(err); // no
})

通过Promise处理异步,先执行异步操作,不关心如何处理结果,通过Promise对象的返回成功还是失败,在将来的某个时刻执行结果处理函数。

  • resolve && reject
    上面代码我们通过 resolve 方法把 Promise 的状态置为完成态(Resolved),这时 then 方法就能捕捉到变化,并执行“成功”情况的回调。
    而 reject 方法就是把 Promise 的状态置为已失败(Rejected),这时 then 方法执行“失败”情况的回调(then 方法的第二参数)。

Promise实现多层回调

同样三级回调的代码我们再使用Promise重构一遍

new Promise((resolve,reject)=>{
	$.get('/getList',res=>{
		resolve(res);
	});
}).then(res=>{
	return new Promise((resolve,reject)=>{
		$.get('/getCount',res=>{
			resolve(res);
		});
	});
}).then(res=>{
	return new Promise((resolve,reject)=>{
		$.get('/getDetail',res=>{
			resolve(res);
		})
	});
}).then(res=>{
	//...
});

可以看到无论有多少层回调,都不用互相嵌套,只需要等待Promise对象“通知“执行即可。

Promise.all

当需要进行多步没有关联逻辑的异步操作时,可以使用Promise.all

Promise.all([
	$.get('/getList'),
	$.get('/getCount'),
	$.get('/getDetail')
]).then(([data1,data2,data3])=>{
	//then回调的参数是一个数组,顺组数序就是异步操作书写顺序
	console.log(data1,data2,data3);
},err=>{
	console.log(err);
});
  • all方法中的参数应该是Promise对象,因为ajax函数返回的对象就是promise对象所以这里是可以执行的;
  • 此种方式只适用于异步操作之间无逻辑关联;
  • 不论异步操作执行顺序如何,最后都会按照书写顺序返回(data1,data2,data3是按照异步操作书写顺序返回);
  • 如果如其中一个出错就会执行错误回调;

Promise.race

race的用法与all相似,不同点就是all会等所有异步操作全部执行完后再执行then回调,而race中只要有一个异步操作执行完成就立刻执行then回调。

Promise.race([
	new Promise(function(resolve, reject){
        setTimeout(function(){
            console.log('函数一执行!');
            resolve('11');
        }, 1000);
    }),
    new Promise(function(resolve, reject){
        setTimeout(function(){
            console.log('函数二执行!');
            resolve('22');
        }, 1200);
    })
]).then(result=>{
	console.log('then执行');
	console.log(result);
},err=>{
	console.log(err);
});

//执行结果为:
//函数一执行!
//then执行
//11
//函数二执行!

可以看到函数一执行明显要比函数二快,所以执行了函数一后立即执行了then回调,注意这时函数二依然会执行,但是执行后不会再触发then回调的执行。

Promise错误处理

  • 第一种方式,通过then
new Promise((resolve,reject)=>{
	//...
}).then(resSuccess=>{
	//成功
},resError=>{
	//失败
});
  • 第二种方式,catch捕获
new Promise((resolve,reject)=>{
	//...
}).then(resSuccess=>{
	//成功
}).catch(resError=>{
	//失败
});

catch方式更常用,因为不仅仅能捕获到reject传递的参数,还可以捕获到成功的回调中发生的错误。

未完。。。

猜你喜欢

转载自blog.csdn.net/weixin_42397257/article/details/89114273