Promise是什么?
Promise是一种异步解决方案,它是一个构造函数,可以接收一个参数为函数,函数内有两个参数为resolve,reject这两个参数是异步操作成功后或失败后调用的回调函数。
Promise的特点
(1) Promise简单的来说它就是一个容器, Promise对象的状态不受外界的影响, 它就三种状态:pending(进行中)、fulfilled(已成功)、reject(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作结果都无法改变这个状态。
(2) 一旦状态发生改变,就不会再变,任何时候都可以得到这个结果,Promise状态改变只有两种可能,从pending到fulfilled或者从pending到reject,只要状态确定之后,就不会再变了,会一直保持这个结果。
(3) 一旦创建Promise就会立即执行,中途无法取消。
为什么要用Promise?
Promise解决了嵌套回调函数的 " 回调地狱 " Promise是链式的它比回调函数看着没那么恶心,不像回调函数嵌套那么多层。
Promise的优势在于,可以在then方法中继续写Promise对象并返回,然后继续调用then来进行回调操作。
下面写一个基本的Promise用法
var p = new Promise(function(resolve,reject){
resolve('执行了')
})
p.then(function(data){
console.log(data) // 执行了
})
上面代码中,resolve函数是表示成功, then第一个参数的回调函数,接收上面resolve函数中的参数数据。
下面再看一个失败的状态
var p = new Promise(function(resolve,reject){
reject('错误了')
})
p.then(function(data){
console.log(data)
},function(error){
console.log(error) // 错误了
})
上面代码中,then方法中的第二个参数是接收失败时的状态函数。
.catch语法,该方法也是捕获错误的。
p.then(function(data){
console.log(data)
}).catch(function(error){
console.log(error) // 错误了
})
看到上面的代码,可能有的小伙伴就会说,catch和then方法的第二个参数同样都是捕获的错误的,那么它俩有什么区别呢?
then第二个参数
var p = new Promise(function(resolve,reject){
resolve('执行')
})
p.then(function(data){
console.log(data); // 执行
console.log(num);
},function(error){
console.log(error)
})
效果:
上面的代码,说是then的第二个参数是捕获错误的,但是它只捕获Promise实例里的错误,then里面有一个console.log(num) , num没有声明 报错 , 它就捕获不到,catch方法就可以捕获的到,所以我们一般都是使用catch方法。
var p = new Promise(function(resolve,reject){
resolve('执行')
})
p.then(function(data){
console.log(data);
console.log(num);
}).catch(function(error){
console.log(error) // 可以捕获的到
})
上面代码,catch方法可以捕获的到错误,catch可以说是比较强大的。
then链式操作用法
var p = new Promise(function(resolve,reject){
resolve('执行')
})
p.then(function(data){
console.log(data); // 执行
return 123;
}).then(function(data){
console.log(data) // 123
return 456;
}).then(function(data){
console.log(data) // 456
})
上面代码的链式操作,这方法非常的棒,return返回值就是下一个then要捕获的数据,这方法就相当于我们回调函数的层层嵌套,然而Promise链式操作更简洁。
Promise.all方法
all方法非常的方便,它可以执行多个异步操作 ,并且在一个回调中处理所有的返回数据
function fn1(){
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve('我是fn1')
},1000)
})
}
function fn2(){
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve('我是fn2')
},300)
})
}
function fn3(){
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve('我是fn3')
},5000)
})
}
Promise.all([fn1(),fn2(),fn3()]).then(function(data){
console.log(data)
})
上面代码Promise.all方法参数接收一个数组,它的执行呢,数组内的三个参数必须都为resolve状态,都是成功的才行,有一个reject状态就会报错,终止运行,上面代码的定时器异步操作5秒后执行,它会看三个定时器的谁的时间最长而等待它被执行,所以它会在5秒之后,再返回Promise。
Promise.race方法
race方法也是接收一个数组,,只返回其中的一个值,就是定时器谁的时间最短就返回谁,该方法一般都是在进行访问超时时间。
function fn1(){
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve('我是fn1')
},1000)
})
}
function fn2(){
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve('我是fn2')
},300)
})
}
function fn3(){
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve('我是fn3')
},5000)
})
}
Promise.race([fn1(),fn2(),fn3()]).then(function(data){
console.log(data) // fn2
})
上面代码只执行了一个 fn2
下面写一个返回请求超时的列子。
var p = Promise.race([
fetch('http://jsonplaceholder.typicode.com/users'),
new Promise(function (resolve, reject) {
setTimeout(function(){
reject(new Error('当前网络不可用~'))
},3000)
})
]);
p.then(function(data){
return data.json()
}).then(function(data){
console.log(data)
}).catch(function(error){
console.log(error)
})
Promise.resolve方法
该方法是转换为Promise对象,如果转换的该参数不是Promise对象,该方法就会自己新生成一个新的Promise对象,状态为resolve,如果是Promise对象,就不做任何的操作,状态直接为resolve。
Promise.resolve('aaa');
//相当于
new Promise(function(resolve,reject){
resolve('aaa')
})
Promise.reject方法
该方法跟Promise.resolve一样,同上,该方法都不怎么使用,了解就行。
Promise.reject('aaa');
//相当于
new Promise(function(resolve,reject){
reject('aaa')
})
下面看一下Promise和其它的执行顺序。
var p = new Promise(function(resolve,reject){
resolve('我是then调用的')
console.log('我是立即执行')
})
p.then(data=>console.log(data))
console.log(1)
setTimeout(()=>{
console.log('我是定时器')
},0)
效果:
解析:
- Promise创建后就会立即执行,中途无法取消。
- then方法和定时器都是异步的,前者会加入到本轮执行队列的尾部,后者则会加入下一个队列中,所以会先让console.log(1)执行。
- then执行是在本轮的结束时才执行。
- 定时器执行是在下一轮中所以它最后执行。