ES6引入的进行异步编程的解决方案,从语法上说它是一个构造函数。
异步编程包括但不限于:文件操作、数据库操作、AJAX、定时器
为什么要用Promise?
之前进行异步编程直接通过回调函数的方式进行,会导致回调地狱。
实现:
点击按钮, 1s 后显示是否中奖(30%概率中奖)
若中奖弹出 恭喜您中奖
若未中奖弹出 谢谢参与
Title
Promise初体验
Promise构造函数的参数是一个包含异步操作的函数
new Promise((resolve, reject) => {})
该函数有两个参数,resolve和reject,这两个参数同样也是函数形式
const p = new Promise((resolve, reject) => {let n = rand(1, 100)if (n <= 30) {resolve(n) // 将 promise 对象的状态设置为 『成功』} else {reject(n) // 将 promise 对象的状态设置为 『失败』}
p.then((value) => {alert('恭喜您中奖,您的中奖号码为' + value);}, (reason) => {alert('谢谢参与,您的号码为' + reason);})
Promise.then()函数具有两个参数,都是函数形式
基础回调函数形式:
const fs = require('fs')fs.readFile('D:\\code\\wt-promise\\src\\components\\HelloWorld.vue', (err, data) => {if (err) {throw err;} else {console.log(data.toString())}})
Promise封装后:
const fs = require('fs')
let p = new Promise((resolve, reject) => {fs.readFile('D:\\code\\wt-promise\\src\\components\\HelloWorld.vue', (err, data) => {// 如果出错if (err) reject(err);// 如果成功resolve(data);});
});p.then(value => {console.log(value.toString());
}, reason => {console.log(reason);
})
Title
Promise封装AJAX 操作
Title
Promise封装AJAX 操作
封装一个函数 mineReadFile 读取文件内容
function mineReadFile(path) {return new Promise((resolve, reject) => {// 读取文件require('fs').readFile(path, (err, data) => {if (err) {reject(err);} else {resolve(data);}});});
}
其返回一个Promise对象
调用函数,使用Promise.then()的方法
mineReadFile('./resource/content.txt').then((value) => {console.log(value.toString());}, (reason) => {console.log(reason);});
原始需要在readFile的参数里面指定回调函数
使用Promise后,可以在mineReadFIle后面的then函数中指定回调函数,解决回调地狱问题
作用:自动将异步操作封装成一个Promise
// 引入util模块
const util=require('util');
// 引入fs模块
const fs=require('fs');
//返回一个新的函数
let mineReadFile=util.promisify(fs.readFile);mineReadFile('./resource/content.txt').then(value=>{console.log(value.toString());
});
状态:实例对象中的一个属性 【PromiseState】,三个值
实例对象中的另一个属性 【PromiseResult】- 对象的值
保存着异步任务『成功/失败』的结果
成功则执行resolved(),修改Promise对象状态为resolved,在then函数中回调onResolved,返回一个新的Promise对象
失败则执行rejected(),修改Promise对象状态为rejected,在then函数中回调onRejected,返回一个新的Promise对象
executor函数:执行器函数 (resolve,reject)=>{ }resolve函数:{ } 内部异步操作成功时我们调用的函数 value => { }
reject函数:{ } 内部异步操作失败时我们调用的函数 reason => { }
PS!!!
executor会在Promise内部立即同步调用,意味着代码执行到Promise的对象创建时就会执行其构造函数的回调函数,再执行下面的代码:
如这段代码先输出111再输出222
而执行器的异步操作,就在执行器中按照规定的异步顺序执行
Promise.prototype.then()的prototype表示then是Promise的实例对象的方法,如果没有prototype则表示then是promise函数对象的方法(类似于静态方法)
参数为两个回调函数: onResolved,onRejected
onResolved函数:成功的回调函数:(value)=>{ }
onRejected函数:失败的回调函数:(reason)=>{ }
只指定异步操作失败的回调函数,参数只有onRejected
onRejected函数:失败的回调函数:(reason)=>{ }
resolve是Promise类的静态方法,不需要实例就能调用
作用:接受一个参数,直接返回一个成功或失败的Promise对象,快速将一个值封装成一个Promise对象
特点:
如果传入的参数为非Promise对象,则返回的结果为状态为成功的Promise对象
如果传入的参数为Promise对象,则返回的结果为状态为传入的Promise对象的状态,返回结果的值为传入Promise的值
这边会报错是因为传入的Promise状态为rejected,这需要Promise有处理错误的回调函数,通过P2.catch((reason)=>{} )
补上回调函数即可
相反,如果传入的Promise的状态为resolved,则不需要特意补一个回调函数也不会报错
Promise.reject()方法:(reason)=>{}
作用:返回一个值为reason的,状态为rejected的Promise对象
无论传入什么都返回一个状态为失败Promise,即使传入一个成功的Promise对象,返回的Promise的值是传入的成功的Promise对象,但是返回Promise的状态还是失败
作用:返回一个新的Promise,当所有Promise都成功,返回的Promise状态为成功,其结果为所有Promise的结果组成的一个数组;当存在失败的Promise,返回的Promise的状态为失败,其结果为失败的Promise的结果
成功情况:
失败情况
promises:包含 n 个 promise 的数组
注:返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态
Title
三种方式
Title
当promise状态改变为对应状态时都会调用
Title
问题简化:Promise代码运行时,resolve先执行还是then先执行
注意,指定回调和执行回调函数是不一样的,指定回调类似于p.then()中声明有哪些回调函数,执行回调则是在状态确定之后执行之前指定的回调
两种情况都有可能
执行器中是一个同步操作,那么就先做执行器中的操作`再执行then语句即指定回调`例如直接在执行器中直接调用 resolve()/reject()
执行器中是一个异步操作,延长更长时间才调用then()同样可以达到效果
执行器中是异步操作时,会先执行then - 指定回调(但是不执行回调),再回头根据异步操作的顺序进行处理
什么时候才能得到数据? - 回调函数什么时候执行
如下为同步:
Title
如下为异步,需等一秒之后执行:
promise执行器中是一个异步任务,那么就执行then,指定回调;处理执行器中的异步任务,1000ms后改变状态;再执行成功的回调函数,得到数据
Title
then方法返回结果由 then()指定的回调函数执行的结果决定
Title
① 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常
Title
② 如果返回的是非 promise 的任意值, 新 promise 变为 resolved, value 为返回的值
Title
③ 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果
Title
(1) promise 的 then()返回一个新的 promise, 可以看成 then()的链式调用
(2) 通过 then 的链式调用串连多个同步/异步任务
Title
(1) 当使用 promise 的 then 链式调用时, 可以在最后指定失败的回调,
(2) 前面任何操作出了异常, 都会传到最后失败的回调中处理
Title
Title
当没有明确返回一个promise对象,then()也会返回一个Promise对象,状态为【resolved】,结果为【underfined】
Title
和then一样:分成三种情况执行返回值: 是非Promise对象,是一个Promise对象,是抛出异常
获取Promise的成功的结果
await 必须写在 async 函数中, 但 async 函数中可以没有 await
如果 await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理
Title
Promise初体验
//回调函数的方式
fs.readFile('D:\\code\\wt-promise\\src\\hello.text', (err, data1) => {if (err) throw err;fs.readFile('D:\\code\\wt-promise\\src\\hello.text', (err, data2) => {if (err) throw err;fs.readFile('D:\\code\\wt-promise\\src\\hello.text', (err, data3) => {if (err) throw err;console.log(data1 + data2 + data3);});});
});
//async 与 await
async function main() {try {// 如果表达式时Promise对象,await返回的Promise成功的值let data1 = await mineReadFile('D:\\code\\wt-promise\\src\\hello.text');let data2 = await mineReadFile('D:\\code\\wt-promise\\src\\hello.text');let data3 = await mineReadFile('D:\\code\\wt-promise\\src\\hello.text');console.log(data1 + data2 + data3);} catch (e) {console.log(e.code);}
}main();