promise详解
本文主要是对B站尚硅谷的promise做一个总结,直达B站学习
异步调用
JavaScript的执行环境是单线程的、就是一次只能完成一项任务,这个任务执行完成后才能执行下一个,它会阻塞其他任务。这个任务可称为主线程,异步模式可以一起执行多个任务。
常见的异步模式有以下几种:
- 定时器
- 接口调用
- 事件函数
接口调用的方式:
- 原生ajax
- 基于jquery的ajax
- Fetch
- Promise
- Axios
多次异步调用的依赖分析
- 多次异步调用的结果,顺序可能不同步
- 异步调用的结果如果存在依赖,则需要嵌套。但是当进行多层嵌套回调时,会导致代码层过多,很难进行维护和二次开发;而且会导致回调地狱的问题。
promise概述
Promise对象,可将异步操作以同步的流程表达出来。使用promise主要有以下好处:
- 可以很好的解决回调地狱的问题
- 语法简洁。Promise对象提供了简洁的API,使得控制异步操作更加容易。
Promise是一个构造函数,有all、reject、resolve这几个眼熟的方法,原型上有then、catch等同样眼熟的方法。
promise的基本用法
(1)使用new实例化一个promise对选哪个,promise的构造函数中传递一个参数,这个参数是一个函数,该函数用于处理异步任务。
(2)并传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数.
(3)通过promise.then()处理返回结果,这里p指的是promise案例。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="container">
<h2>Promise 初体验</h2>
<button id="btn">点击抽奖</button>
</div>
<script>
function rand(m,n){
return Math.ceil(Math.random() * (n-m+1))+m-1
}
const btn = document.getElementById('btn')
btn.addEventListener('click', function(){
const p = new Promise((resolve, reject) => {
setTimeout(()=>{
let n= rand(1,100)
if(n<=30){
resolve(n)
}else{
reject(n)
}
})
})
p.then((value)=>{
alert('恭喜你!中奖啦!您的中奖金额为' + value)
},(reason)=>{
alert('再接再厉,您的号码为' + reason)
})
})
</script>
</body>
</html>
promise对象的3个状态
初始化状态:pending
成功状态:fullfilled
失败状态:rejected
(1) 当new promise()执行之后,promise对象的状态会被初始化为pending,这个状态是初始化状态。New promise()这行代码,括号里的内容时同步执行的。括号里定义一个function,function有两个参数:resolve和reject;
如果成功了,则执行resolve(),此时,promise的状态会被自动修改为fullfilled;
如果失败了,则执行reject(),此时 promise的状态会被自动修改为 rejected。
(2) promise.then()方法,括号里有两个参数,分别代表两个函数
如果promise的状态是fullfilled,则执行function1里面的内容。
如果promise的状态是rejected,则执行function2里面的内容。
promise的状态改变
- pending 变为 resolved
- pending 变为 rejected
只要这两种状态改变,且一个promise对象只能改变一次,无论变为成功还是失败,都会有一个数据结果,成功的结果一般为value,失败的结果一般为reason。
promise 对象的值
实例对象中的另一个属性 PromiseResult 保存着异步任务 成功/失败 的结果
Resolve
Reject
实例对象中的另一个属性 PromiseResult 保存着异步任务 成功/失败 的结果
Resolve
Reject
Promise.resolve 方法:(value)=>{}
value :成功的数据或promise对象
说明: 返回一个成功/失败的promise对象
Promise.reject 方法:(reason)=>{}
Reason:失败的原因
说明:返回一个失败的promise对象
Promise.all 方法(promise)=>{}
Promise :包含n个promise的数组
说明:返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败了就失败。
Promise.race 方法:(promise)=>{}
Promise:包含n个promise的数组
说明:返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态。
Promise如何串联多个操作任务?
(1) promise的then()返回一个新的promise,可以看成then()的链式调用;
(2) 通过then的链式调用串联多个同步/异步任务
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('OK')
},1000)
})
// then的返回结果也是一个promise
p.then(value =>{
return new Promise((resolve,reject)=>{
resolve('success')
}).then(value=>{
console.log(value)// success
}).then(value=>{
console.log(value)// undefined
})
})
</script>
</body>
</html>
Promise的异常穿透?
(1) 当使用promise的then链式调用时,可以在最后指定失败的回调;
(2) 前面任何操作出了异常,都会传到最后失败的回调中处理。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var p = new Promise((resolve,reject)=>{
// reject('Error')
resolve('default!')
})
p.then(value=>{
throw '失败啦'
}).then(value=>{
console.log('111')
}).then(value=>{
console.log('222')
}).catch(reason=>{
console.warn(reason)
})
</script>
</body>
</html>
中断promise链
(1) 当使用promise的then链式调用时,在中间中断,不载调用后面的回调函数。
(2) 办法:在回调函数中返回一个pending状态的promise对象。
<script>
var p = new Promise((resolve,reject)=>{
// reject('Error')
resolve('default!')
})
p.then(value=>{
console.log('333')
return new Promise(()=>{})//返回的promise状态为pending,then()方法只有在promise状态改变的时候才会执行,如果一直保持pending状态,这后续的then()方法都不会执行
}).then(value=>{
console.log('111')
}).then(value=>{
console.log('222')
}).catch(reason=>{
console.warn(reason)
})
</script>
ES6 async和await函数
async函数返回一个promise对象,可以使用then方法添加回调函数。
Async 函数中可能有await表达式,async函数执行时,如果遇到await就会先暂停执行,等到触发的异步操作完成后,恢复async函数的执行并返回解析值。
Await关键字仅在async function中有效。如果在async function 函数体外使用 await ,你只会得到一个语法错误。
await表达式
(1) await右侧的表达式一般为promise对象,但也可以是其他的值;
(2) 如果表达式是promise对象,await返回的是promise成功的值;
(3) 如果表达式是其他值,直接将此值作为await的返回值。
注意:
(1) await必须写在async函数中,但async函数中可以没有await
(2) 如果await的promise失败了,就会抛出异常,需要通过try…catch捕获处理。