Promise 是Es6新增的异步编程的一种方案。从语法上讲,Promise 是一个对象,它可以获取异步操作的消息。Promise对象, 可以将异步操作以同步的流程表达出来。
一、使用 Promise 主要有以下好处:
1.可以很好地解决回调地狱的问题(避免了层层嵌套的回调函数)。
2.语法非常简洁。Promise 对象提供了简洁的API,使得控制异步操作更加容易。
回调地狱的举例:
假设买菜、做饭、洗碗都是异步的。
但真实的场景中,实际的操作流程是:买菜成功之后,才能开始做饭。做饭成功后,才能开始洗碗。这里面就涉及到了多层嵌套调用,也就是回调地狱。
二、Promise 的基本用法
(1)使用new实例化一个Promise对象,Promise的构造函数中传递一个参数。这个参数是一个函数,该函数用于处理异步任务。
(2)并且传入两个参数:resolve和reject,分别表示异步执行成功后的回调函数和异步执行失败后的回调函数;
(3)通过 promise.then() 处理返回结果。这里的 p 指的是 Promise实例。
三、Promise 自带的API提供了如下实例方法:
promise.then():获取异步任务的正常结果。
promise.catch():获取异步任务的异常结果。
代码举例如下:
//基本语法
var p = new Promise(function(resolve,reject){
//进行异步请求
//如果异步请求成功就把请求结果放入resolve
if (a == 1) {
resolve(‘请求成功的信息’)
} else {
//如果异步请求失败就把请求结果放入reject
reject(‘请求失败的信息’)
}
});
p.then(
function (res1) {//promise的第一个then中的第一个函数 function 1 用来处理resolve
console.log(res1);//请求成功的信息
},
/* function(res2){//promise的第一个then中的第二个函数 function 2 用来处理reject
console.log(res2);//请求失败的信息
} */
).catch(function (er) {//捕获错误
if (er) {
console.log(er);//请求失败的信息
}
}).then(function (res2) {//第二个then 是第一个then结束后的回调函数
console.log('处理完成');
})
语法总结:
1.promise 的参数是一个回调函数,回调函数中有两个 参数人别是resolve, reject resolve 用来返回异步请求成功的结果 reject 用来返回异步请求失败的结果
- promise 的对象将异步请求结果保存后,需要使用第一个 .then来获取结果resolve函数返回的结果 .catch 获取reject 返回的结果。当然第一个.then()方法,括号里面有两个参数,分别代表两个函数 function1 和 function2;
*如果promise的状态为fullfilled(意思是:如果请求成功),则执行function1里的内容
*如果promise的状态为rejected(意思是,如果请求失败),则执行function2里的内容
(上述问题可以查看代码~)
3.promise 还可以使用 第二个.then 它是第一个.then的回调函数,这里可以继续处理其他逻辑(一般不经常使用)
四、Promise 自带的API提供了如下对象方法:
Promise.all():并发处理多个异步任务,所有任务都执行成功,才能得到结果。
Promise.race(): 并发处理多个异步任务,只要有一个任务执行成功,就能得到结果。
Promise.all()语法
代码如下:
var p1 = new Promise(function(resolve,reject){
setTimeout(function(){
resolve('p1完成')
},1000)
})
var p2 = new Promise(function(resolve,reject){
setTimeout(function(){
resolve('p2完成')
},2000)
})
var p3 = new Promise(function(resolve,reject){
setTimeout(function(){
resolve('p3完成')
},3000)
})
Promise.all([p3,p2,p1]).then(function(res){
console.log(res)
// p3,p2,p1是我调用的顺序 ["p3完成", "p2完成", "p1完成"]是我返回的结果
// 可以看得出来,我们控制了 3个异步请求的返回顺序
})
总结:promise.all 的使用场景就是,可以同时处理多个异步请求,并控制他们返回的【结果的顺序】
注意:promise.all中的 任何一个请求失败,将不会有返回结果。
prmise.race的用法
···
var p1 = new Promise(function (resolve, reject) {
setTimeout(function(){
resolve('p1');
},1000)
}) ;
var p2 = new Promise(function (resolve, reject) {
setTimeout(function(){
resolve('p2');
},30)
})
Promise.race([p1, p2]).then(function (data) {
console.log(data); // 'p2' 这里只返回一个执行最快的结果
})
···
五、promise 结合 await async 封装接口api
···
var token = JSON.parse(localStorage.getItem('userIfo')).remember_token
function http(url, type, data = '') {
let p = new Promise((resolve, reject) => {
if (token) {
$.ajax({
headers: {Authorization: 'Bearer ' + token },
url,
type,
data,
success: (res) => {
resolve(res)
},
error: (er) => {
reject(er)
}
})
}
})
return p
}
function getNav() {
return http(`http://120.xx.xx.103:84/api/menu/info`, 'post')
}
function getList(n,status,nickname,mobel) {
return http(`http://120.xx.xx.103:84/api/user?page=${n}&limit=10&status=${status}&nickname=${nickname}& mobile=${mobel}&`, 'get')
}
// 调用
async function List(n, status, nickname, mobel) {
var list = await getList(n, status, nickname, mobel)
// 这个将 异步的接口封装,同步化
console.log(list); // 这里以同步的方式 获得异步结果
}
···
总结:Async-Await (语法参考上方代码)
Async-Await可以说是异步编程的最高境界,就是隧道尽头的亮光,很多人认为他是异步操作的终极解决方案,它和promise的关系不存在谁替换谁,因为它是寄生于promise。
async和await在干什么,async用于申明一个function是异步的,而await可以认为是async wait的简写,await只能在async这个函数里面使用,表示在这里等待一个异步方法(promise返回结果后)再继续执行。
需要注意的就是await是强制把异步变成了同步,这一句代码执行完,才会执行下一句,所以async/await需要谨慎使用。
javascript的宏任务和微任务
看一道常见面试题
setTimeout(
function(){
console.log('1') //异步 4
}
);
new Promise(
function(resolve, reject){
resolve()
console.log('2'); //同步 1
}).then(function(){
console.log('3') //异步 3
});
console.log('4'); ///同步 2
此题输出顺序为 2=>4=>3=>1 因为js代码执行机制为先执行同步代码(也叫顺序执行),同步代码执行完毕后才会执行异步代码,setTimeout和prominse.then()都是异步代码,但是prominse.then()会比setTimeout先执行。