在了解Promise之前,要先知道什么是异步,什么是同步。 大概可以这么理解,所谓的异步,就是操作跟操作之间是没关系的,这就同时带来一个特点,可以同时进行多个操作。 而同步操作之间是相关的,同时只能做一件事,必须等前一件事做完了,后面的才能进行。 异步有多个优点,但也有缺点,那就是代码会更复杂。而同步的优点就是代码简单。
比方说用异步操作请求一个电商网站的数据,大概是这样的:
ajax('/banners',function(banner_data){
ajax('/hotsItems',function(hotsItems_data){
ajax('/slides',function(slides_data){
//......
},function(){
alert("error")
})
},function(){
alert("error")
})
},function(){
alert("error")
})
//做多重的异步操作,会导致经典的回调地狱
这个时候用多重嵌套,会显得特别麻烦,而用同步操作会显得简单,它会走完第一个数据之后,再走下一个:
//同步版,假如有个ajax_async:
let banner_data = ajax_async('/banners');
let hotsItems_data = ajax_async('/hotsItems');
let slides_data = ajax_async('/slides');
...
//但用户体验差,也没回卡死
用异步操作,性能高,用户体验好,但是代码复杂;但同步操作,页面可能会卡死,也用不得。
Promise--消除异步操作
Promise是异步编程的一种解决方案,比传统的解决方案--回调函数和事件,更合理更强大。用同步一样的方式,来书写异步代码
。
本质上,一个promise是某个函数返回的对象,你可以把回调函数绑定在这个对象上,而不是把回调函数当作参数传进函数。
//当我们需要一个promise的时候,需要new一个promise对象,里面接收一个函数作为参数,里面异步的代码都写在函数里面,这个函数有两个参数:resolve,reject
let p = new Promise(function(resolve,reject){
//异步代码
//resolve--成功
//reject--失败
});
//-------------
//此处用promise封装一个ajax操作
//此处已引入一个jquey文件
let p = new Promise(function(resolve,reject){
$.ajax({
url:'文件1路径',
dataType:'json',
success(data){
//成功的时候调用resolve
resolve(data)
},
error(err){
//失败的时候调用reject
reject(err)
}
})
});
//当promise调用有结果了,会调用then,里面有两个函数作为参数,
p.then(function(data){
//成功了调用这个函数
console.log(data)
alert('成功'+data)
},function(err){
//失败会调用这个函数
console.log(err)
alert('失败'+err)
})
假如要封装两个promise,要如何操作?promise对象上有一个方法all(),里面接收一个数组作为参数,可以把两个promise扔进去,然后再使用then方法
let p1 = new Promise(function(resolve,reject){
$.ajax({
url:'文件1路径',
dataType:'json',
success(data){
resolve(data)
},
error(err){
reject(err)
}
})
});
let p2 = new Promise(function(resolve,reject){
$.ajax({
url:'文件2路径',
dataType:'json',
success(data){
resolve(data)
},
error(err){
reject(err)
}
})
});
Promise.all([
p1,p2
]).then(function(arr){
//全都成功
//会有一个数组作为结果,里面装的是文件1 2 的数据,所以要分解出两个结果
let [res1,res2] = arr;
console.log(res1);
console.log(res2);
},function(){
//至少有一个失败
})
这时候会发现一个问题:这里要写两个Promise对象,但它们只有地址不一样,其他都一样,那可以封装一个方法,把创建好的Promise对象返回出去:
function createPromise(url){
return new Promise(function(resolve,reject){
$.ajax({
url:url,
dataType:'json',
success(data){
resolve(data)
},
error(err){
reject(err)
}
})
});
}
Promise.all([
createPromise('文件1路径');
createPromise('文件2路径');
]).then(function(arr){
let [res1,res2] = arr;
console.log(res1);
console.log(res2);
},function(){
//至少有一个失败
})
当使用高版本jquery的时候,这个jquery会自带Promise。
Promise.all([
$.ajax({url:'文件1路径',dataType:'json'}),
$.ajax({url:'文件2路径',dataType:'json'})
]).then(function(){
//成功
},function(){
//失败
})
有了Promise之后异步,大概是这样的;
Promise.all([$.ajax(),$.ajax()]).then(result=>{
//成功
},err=>{
//失败
})
//异步的本质没有变,有异步的优势,不影响用户体验,写法上也没比同步复杂多少
Promise的其他用法
Promise.race:可以同时读多个资源,谁先来先读谁,用法跟all类似
Promsie.race([
$.ajax({url:'http://a1.baidu.com/data'}),
$.ajax({url:'http://a2.baidu.com/data'}),//如果a2快,先读a2
$.ajax({url:'http://a3.baidu.com/data'}),
$.ajax({url:'http://a4.baidu.com/data'}),
$.ajax({url:'http://a5.baidu.com/data'})
])
以上是Promise的简单入门,接下来还有Promise进阶及原理实现,欢迎关注。