Promise的基本概念
Promise是es6出来的一个对象,主要是用来封装异步代码,是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。(ps:什么是原型:javascript中的原型与原型链_傻小胖的博客-优快云博客_javascript原型和原型链)
因为异步代码要拿数据可能就需要回调函数,而回调函数嵌套太多就引发回调地狱。
所以用Promise来封装异步代码后可以解决回调地狱的问题!
Promise对象的特点
Promise对象有以下两个特点。
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
(3)promise对象都会有两个方法,一个叫then,一个叫catch。当这个promise对象内部的resolve被调用,就会执行then里的代码。当这个promise对象内部的reject被调用,就会执行catch里的代码。
构建Promise
现在我们就来构建一个promise来方便大家理解。
先来看一下promise结构
const ps = new Promise((resolve, reject) => {
})
封装异步代码:异步代码如果执行成功要调用resolve 如果执行失败要调用 reject
现在正式开始构建:
第一步:写js文件无论什么时候都要先导入fs模块
const fs = require('fs')
第二步: 实例化一个promise对象,并包装一段异步函数。
const ps = new Promise ((resolve,reject) => {
fs.readFile('./1.txt',(err,data) => {
if(!err) {
// 没有错,读取成功,调用resolve并传入读取到的结果
resolve(data)
} else {
// 读取失败,调用reject,并传入错误信息。
reject(err)
}
})
})
resolve和rejected是两个函数,如果异步代码执行成功,调用resolve,一般还会传入异步的结果
上面我们说到promise对象的两个方法,我们现在就来展示一下then和catch
resolve被调用,就会执行then里的代码。当这个promise对象内部的reject被调用,就会执行catch里的代码。
.then( res => {
console.log('then调用:' + res);
})
.catch( err => {
console.log('catch调用:' + err);
})
这里是异步代码执行成功,所以是then被调用,调用的是我们上面已经写好的1.txt文档
promise的同步异步代码顺序
我们现在来说一下本次的重点内容promise的同步异步顺序,上面对promise已经有了一个基本的了解,所以我们直接用代码演示
console.log(1);//同步代码
new Promise((resolve,reject)=>{
console.log(2);//同步代码
resolve()
console.log(3);//同步代码
}).then(rew =>{
console.log(4);//异步代码
})
console.log(5);//同步代码
promise对象本身是同步的 里面的方法是异步的,所以resolve()与reject()是异步代码
执行顺序为先打印同步代码 再打印异步代码。所以就此推断最终输出结果为12354,看一下运行结果:
然后我们看一下今日的作业
console.log(1);
new Promise((resolve,reject) => {
console.log(2);
setTimeout(() => {
console.log(6);
// 产生一个0到10的随机数
let num = Math.floor(Math.random() * 11)
// 如果大于等于5就resolve
if(num >= 5){
resolve()
} else {
// 否则就reject
reject()
}
},1000);
console.log(3);
})
.then(res => {
console.log(4);
})
.catch(err => {
console.log(7);
})
结果为1,2,3,6,4
为何会如此?我们来逐个解释:
1因为是定义在全局自然是同步代码与promise的特性无关
2虽然被promise包括但并不是定义在promise方法里面,所以也是同步,这个我们上面也已经做过解释promise对象本身是同步的 里面的方法是异步的
3的情况与2一样,也是同步代码所以这三个数字按上下排列顺序进行
6在promise的方法里面,上面也已经解释过了promise对象本身是同步的 里面的方法是异步的,所以是异步代码
4和6情况一致,然后他们两个按上下顺序依次打印
7为何不执行是因为当这个promise对象内部的resolve被调用,就是异步代码执行成功就会执行then里的代码。当这个promise对象内部的reject被调用,就会执行catch里的代码。而这里异步代码执行成功已经打印了6,自然就不会打印7