-
Promise
是ES6
新增的语法,解决了回调地狱的问题。 -
Promise存在三个状态(state)pending、fulfilled、rejected
pending(等待态)为初始态,并可以转化为fulfilled(成功态)和rejected(失败态)
-
可以把
Promise
看成一个状态机。初始是pending
状态,可以通过函数resolve
和reject
,将状态转变为resolved
或者rejected
状态,状态一旦改变就不能再次变化。
- Promise是什么
console.log(Promise)
console.dir(Promise)
// console.log()会在浏览器控制台打印出信息
// console.dir()可以显示一个对象的所有属性和方法
2.new 一个 Promise实例出来
var p = new Promise (function(resolve,reject){
// Promisede 的构造函数接受一个参数,是函数,
//并且传入两个参数:resolve,reject ,
//分别表示异步操作执行成功后的回调函数和异步操作执行失败之后的回调函数,
//resolve将Promise的状态设置为fullfiled,reject将Promise的状态设置为rejected
})
Promisede 的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject ,分别表示异步操作执行成功后的回调函数和异步操作执行失败之后的回调函数,resolve将Promise的状态设置为fullfiled,reject将Promise的状态设置为rejected
3.Promise对象上有then、catch方法
function runAsync(){
var p = new Promise (function(resolve,reject){
// Promise 本身是同步的,现在在其内部开启异步操作
setTimeout(function(){
console.log("执行完成");
resolve('数据')
},1000)
})
return p;
//return 出了Promise对象
}
runAsync(); //执行这个函数后,我们得到一个Promise对象,而Promise对象有then,catch方法
runAsync().then(function(data){
// 在runAsync()的返回上直接调用then方法,then接收一个参数,是函数,并且会拿到runAsync中调用resolve时传入的参数
// then可以在runAsync这个异步操作执行完后被执行
console.log(data) //数据
// then可以拿到resolve(异步操作执行成功后的回调函数)里的数据
})
4.Promise的链式调用
1.从表面上看,Promise只是能够简化层层回调的写法(也可以解决回调地狱的问题),而实质上Promise的精髓时“状态”,用维护状态、传递状态的方式使回调函数能够及时调用
// 从表面上看,Promise只是能够简化层层回调的写法(也可以解决回调地狱的问题),而实质上Promise的精髓时“状态”,用维护状态、传递状态的方式使回调函数能够及时调用
function runAsync1(){
var p = new Promise (function(resolve,reject){
setTimeout(function(){
console.log("异步任务1执行完成");
resolve('数据1')
},1000)
})
return p;
}
function runAsync2(){
var p = new Promise (function(resolve,reject){
setTimeout(function(){
console.log("异步任务2执行完成");
resolve('数据2')
},2000)
})
return p;
}
function runAsync3(){
var p = new Promise (function(resolve,reject){
setTimeout(function(){
console.log("异步任务3执行完成");
resolve('数据3')
},3000)
})
return p;
}
// 通过then实现层层调用,可以避免回调地狱的问题
runAsync1().then(function(data){
console.log(data);
return runAsync2();
}).then(function(data){
console.log(data);
return runAsync3();
}).then(function(data){
console.log(data);
})
5.reject的用法和catch方法
1.reject是异步操作执行失败后的回调函数,reject的作用是把Promise的状态设置为rejected,然后我们就能在then中捕捉到,然后执行"失败"情况下的回调
2.catch的用法:类似于then的第二个参数,用来指定reject的回调,但是他还有一个作用,可以执行resolve的回调(then中的第一个参数)
// reject是异步操作执行失败后的回调函数,reject的作用是把Promise的状态设置为rejected,然后我们就能在then中捕捉到,然后执行"失败"情况下的回调
function getNumber(){
var p = new Promise(function (resolve,reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*10);
if(num<=5){
resolve(num)
}else{
reject("数字>5")
}
},1000)
});
return p;
}
// getNumber().then( //then的第一个参数,用来指定resolve的回调
// function(data){
// console.log("resolved")
// console.log(data)
// },
// function(reason,data){ //then的第二个参数,用来指定reject的回调
// console.log('rejected')
// console.log(reason) //拿到reject里的数据
// }
// )
// catch的用法:类似于then的第二个参数,用来指定reject的回调,但是他还有一个作用,可以执行resolve的回调(then中的第一个参数)
// getNumber().then(
// function(data){
// console.log("resolved")
// console.log(data);
// }).catch(function(reason){
// console.log("rejected");
// console.log(reason)
// })
getNumber().then(
function(data){
console.log("resolved")
console.log(data);
console.log(somedata); //somedata没有定义 按道理应该报错,阻塞程序进行,但是 下面的rejected依旧能被打印出来
也就是说,进到catch方法里面去了,而且把错误信息原因传到了reason参数中。即便是有错误的代码也不会报错了,这与我们的try/catch语句有相同的功能。
}).catch(function(reason){
console.log("rejected"); //rejected
console.log(reason) //ReferenceError: somedata is not defined
})
6.Promise.all的用法
1. Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。
2.Promise.all接受一个数组参数,里面的值最终都返回Promise对象,这样,三个异步操作是并行执行,等他们都执行完后才会进到then里面。
3.那么三个异步操作返回的数据都到哪里去了,都在then里面,all会把所有异步操作结果放进一个数组中传给then,就是下面的results
4.all方法执行时间是谁最慢,就以谁为准执行回调
5.Promise.race方法用法一样,只是谁最快,就以谁为准执行回调
// Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调
function runAsync1(){
var p = new Promise (function(resolve,reject){
setTimeout(function(){
console.log("异步任务1执行完成");
resolve('数据1')
},1000)
})
return p;
}
function runAsync2(){
var p = new Promise (function(resolve,reject){
setTimeout(function(){
console.log("异步任务2执行完成");
resolve('数据2')
},2000)
})
return p;
}
function runAsync3(){
var p = new Promise (function(resolve,reject){
setTimeout(function(){
console.log("异步任务3执行完成");
resolve('数据3')
},2000)
})
return p;
}
function runAsync4(){
var p = new Promise (function(resolve,reject){
setTimeout(function(){
reject('失败')
},2000)
})
return p;
}
let a = Promise.reject('失败')
// Promise.al可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。
// Promise.all接受一个数组参数,里面的值最终都返回Promise对象,这样,三个异步操作是并行执行,等他们都执行完后才会进到then里面。
// 那么三个异步操作返回的数据都到哪里去了,都在then里面,all会把所有异步操作结果放进一个数组中传给then,就是下面的results
// all方法执行时间是谁最慢,就以谁为准执行回调
// 成功 返回数组
// Promise
// .all([runAsync1(),runAsync2(),runAsync3()])
// .then(function(results){
// console.log(results)
// })
// 异步任务1执行完成
// 异步任务2执行完成
// 异步任务3执行完成
// ['数据1', '数据2', '数据3']
// 失败:最先被reject失败状态的值
Promise
.all([runAsync1(),runAsync2(),runAsync3(),a])
.then(function(results3){
console.log(results3)
}).catch(err=>console.log(err))
// Promise.race方法用法一样,只是谁最快,就以谁为准执行回调
// Promise
// .race([runAsync1(),runAsync2(),runAsync3()])
// .then(function(results2){
// console.log(results2)
// })
// 异步任务1执行完成
// 数据1
// 异步任务2执行完成
// 异步任务3执行完成