🐸 一 promise是什么?
es6提供了原生对象promise。
promise的意思是未来将要做的事,用来传递异步操作的消息。
1.抽象表达
promise是ES6新的API
promise是JS进行异步编程的新的解决方案,以前单纯使用回调函数
2.具体描述
从语法来说,promise是一个构造函数
从功能来说,promise对象用来封装一个异步操作并获得其成功/失败的结果。
构造函数是什么:一种特殊的方法,定义构造函数时首字母要大写。
任何函数都可以作为构造函数存在,与普通函数的区分主要从功能进行区分。
其主要功能是初始化对象,特点是和new一起使用。
new是在创建对象,从无到有。构造函数是给初始化对象添加属性和方法。
🐸二 异步编程
同步任务:在主线程队列中,只有前一个任务完成才会执行下一个任务。
异步任务:不进入主线程队列,而是进入异步队列,前一个任务的完成与否不影响后一个任务的执行。
setTimeout(function (){
console.log('执行了回调函数')
},3000)
console.log(111)
// 111
// 执行了回调函数
代码中呈现的是`异步操作`,顺序是:先打印出111,定时器时间到,再执行定时器内的回调
下面是一些常见的异步操作:
- fs文件操作:
require('fs').readFile('./index.html', (err,data)=>{})
- 数据库操作
- AJAX
$.get('/server', (data)=>{})
- 定时器
🐸三 promise的状态改变
promise对象有2个特点:
1.对象的状态不受外界影响。Promise对象代表一个异步操作,有3个状态:
pending: 初始状态,非成功或失败状态
resolved:操作成功完成
reject:操作失败
只有异步操作的结果,可以决定当前是哪种状态,任何其他手段都无法改变promise状态,这也是promise名字的含义:「承诺」。 2.一旦状态改变,就不会再变,任何时候都可以得到这个状态。也就是说,状态改变只有这2种情况:
- pending -> resolved
- pending -> reject
**说明:
只有这2种变化,且一个promise只变化一次。
无论是成功、失败,都会有一个结果数据。
状态变化之后就凝固了。就算你再加回调函数,也只会再次得到原结果。这与事件(Event)完全不同,事件错过之后再监听是得不到结果的。
🐸四 promise的优缺点
优点:
有了promise,可以把异步操作清晰明了的写出来,避免旧时的回调函数层层嵌套。
promise提供统一的接口,使异步操作更简单。
缺点:
无法取消:一旦新建就会立即执行,无法在中途取消。
如果不设置回调函数,promise内部抛出的错误,无法反应到外部。
在pending状态时,无法得知目前函数执行到哪个状态了(是刚开始还是即将结束了).
🐸五 promise的基本流程
stateDiagram-v2
newPromise(),pending状态,执行异步操作 --> promise对象resolved状态
newPromise(),pending状态,执行异步操作 --> promise对象reject状态
promise对象resolved状态 --> 回调onResolved(),.then()
promise对象reject状态 --> 回调onReject(),.then()/.catch()
回调onResolved(),.then() --> 新的promise对象
回调onReject(),.then()/.catch() --> 新的promise对象
🐸六 promise的示例
抽奖系统:点击抽奖按钮,一秒后展示是否中奖(30%概率中奖),恭喜或者再接再厉。
//随机数
methords: {
rand(m, n){
let num = Math.ceil(Math.random() * (n - m + 1)) + m - 1
}
fn_click(){
const p = new Promise((resolve, reject) => {
setTimeout(() =>{
let n = this.rand(1, 100)
if(n < 30){
resolve(n)
} else {
reject(n)
}
}, 1000)
})
p.then(value => {
alert('您的中奖号码为' + value)
}, reason => {
alert('再接再厉')
})
},
}
Promise的.then方法
- .then方法的返回值也是一个Promise对象。
对于已经实例化过的Promise对象可以调用myPromise.then(),传入resolve 和 reject 方法作为回调。
- 当需要串联多个任务时,可以使用.then 方法。
let p = new Promise( (resolve, reject) => {
resolve('OK')
})
p.then(value =>{
return new Promise( (resolve, reject) => {
resolve('success')
})
}).then(value => {
console.log(value)
}).then(value => {
console.log(value)
})
解释:
p是一个Promise对象,状态resolve,返回值是OK。
第一个.then,接收p这个promise的成功回调,这个回调内部的返回值又是一个promise,回调promise的状态是成功,值是success,所以可以用.then接收这个成功
第二个 .then,返回的也是一个promise,接收第一个.then返回的promise的成功返回值success,所以console'success'。但是在.then的回调内部没有return值,所以默认返回值为undefined,undefined不是一个promise,所以状态是resolve,参考https://blog.csdn.net/weixin_59731784/article/details/124532246
第三个.then,返回的也是一个promise,因为第二个.then返回值是undefined,不是一个promise,所以可以从.then获取值,返回值是undefined。所以console undefined
Promise的.catch方法
上面的写法可以简化为.cetch方法
p.then(value => {
alert('您的中奖号码为' + value)
}).catch(reason => {
alert('再接再厉')
})
总结:promise.then方法接受2个参数,成功value和失败reason。promise.then.catch方法,前面成功回调,catch捕捉失败回调。