Promise笔记
异步编程
- fs 文件操作
require('fs').readFile('./路径',(err,data)=>{})
- 数据库操作
- AJAX
$.get('/server',(data)=>{})
- 定时器
setTimeout(()=>{},2000)
Promise
是ES6引入的js中进行异步编程的新解决方案
旧方案是单纯使用回调函数
- 语法看来,是一个构造函数,可以进行对象的实例化
- 功能看来,promise对象可以用来封装一个异步操作并且可以获取其成功/失败的结果值
Promise的状态
指的是实例对象中的一个属性 PromiseState
- pending 未决定的状态值
- resoolved / fullfilled 成功的状态值
- rejected 失败的状态值
状态改变(不能从成功变成失败,也不能从失败变成成功,只能从pending转变)
- pending变为resolved
- pending变为rejected
一个promise对象只能改变一次状态,无论变成成功还是失败,都会有一个结果数据,
成功的结果数据为value,失败的结果数据为reason
Promise状态的值
指的是实例对象中的另一个属性 PromiseResult
保存的是异步任务 成功或失败 的结果
可以改变PromiseResult的值只有两种:
- resolve
- reject
PromiseAPI
-
promise构造函数:Promise(excutor){}
1.excutor函数:执行器 (resolve,reject)=>{}
2.resolve函数:内部定义成功时,调用的函数 value=>{}
3.rehect函数:内部定义失败时,调用的函数:reason=>{}
excutor会在Promise内部立即
同步调用,异步操作再执行器中执行
-
Promise.prototype.then方法:(onResolved,onRejected)=>{}
1.onResolved函数:成功的回调函数 (value) =>{}
2.onRejected函数:失败的回调函数 (reason) =>{}
指定用于得到成功value的成功回调和用于得到失败reason的失败回调返回一个新的promise对象
-
Promise。prototyph.catch方法:(onRejected)=>{}
1.onRejeted函数:失败的回调函数(reason)=>{} -
Promise.resolve方法:(value)=>{}
1.value:成功的数据或promise对象
返回一个成功/失败的promise对象
如果传入的参数为 非 Promise类型的对象,则返回的结果为成功的promise对象
let p1 = Promise.resolve(521)
如果传入的参数为 Promise对象,则参数的结果决定了resolve的结果
let p2 = Promise.resolve(new Promise((resolve,reject)=>{ // 参数的结果为成功,p2的结果就是成功的promise对象 resolve('ok') // 参数的结果为失败,p2的结果就是失败的promise对象 // reject('error') })) console.log(p2); // p2是失败的promise对象,解决报错 p2.catch(reason=>{ console.log(reason); })
-
Promise.reject方法:(reason)=>{}
1.reason:失败的原因
总是返回一个失败的promise对象
无论传入的参数是什么类型 都是失败的promise对象
即使传入的是成功的Proimise对象,返回的结果依旧为失败的promise对象
传入什么s失败的结果就是什么
-
Promise.all方法:(promises)=>{}
1.promises:包含n个promise的数据
返回一个新的promise,只要所有的promise都成功返回的才是成功的promise,只要有一个失败就直接失败
成功的结果:每一个promise对象他们的结果组成的一个数组
失败的结果:在这个数组当中,失败的promise对象是他失败的结果(先出错的primise对象的结果)
-
Promise.race 方法:(promises)=>{}
1.promises:包含n个promise的数组
返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态(不管有多少个promise,只取第一完成的promise对象的结果)
promise的几个关键问题
-
如何改变 promise的状态
1.resolve(value)函数:如果当前是pending就会变成resolved/fullfilled(成功)resolve('ok') //pending => fullfilled/resolved
2.reject(reason)函数:如果当前是pending就会变成rejected(失败)
reject('error) //pending => rejected
3.抛出异常:如果当前是pending就会变成rejected(失败)
throw ''出错了 //pending => rejected
-
一个promise指定多个成功/失败的回调函数,都会被调用吗?
当promise的状态 pending 改变为对应状态时都会被调用
-
改变promise状态(resolve/reject)和指定回调函数(then)谁先谁后?
1.都有可能,默认先执行改变状态在执行指定回调,指定回调then先执行再执行改变状态,(在改变状态中吧同步改成异步)
2.在执行器中直接调用resolve()/reject(),(同步)就是先改状态再指定回调,也可以.then回调函数中加定时器来延长.then的调用
3.什么时候才能拿到数据?(回调函数.then什么时候执行 就什么时候拿到数据)
如果先指定的回调,状态改变以后,再去调用成功或失败的结果
如果先改变的状态,.then方法在调用的时候就会执行回调函数拿到数据,处理成功或失败的结果
-
promise如何串联多个操作任务
1.promise的then()返回一个新的promise,可以开成then()的链式调用
2.通过then的链式调用串联多个同步/异步任务let p = new Promise((resolve,reject)=>{ setTimeout(() => { resolve('ok') }, 2000); }) p.then(value=>{ // ok console.log(value); // 返回一个成功的promise return new Promise((resolve,reject)=>{ resolve('success') }) }).then(value=>{ // success console.log(value); }).then(value=>{ // 因为上面的then返回的是一个全新的promise对象,但是他没有返回值,所以这里输出的undifund console.log(value); })
-
promise异常穿透?
1.当时用promise的then链式调用时,可以再最后指定失败的回调.catch(reason=>{})
2.前面任何操作出了异常,都会传到最后失败的回调中处理let p = new Promise((resolve,reject)=>{ setTimeout(() => { resolve('ok') // reject('Error') }, 2000); }) p.then(value=>{ // console.log('111'); throw 'error' }).then(value=>{ console.log('222'); }).then(value=>{ console.log('333'); }).catch(reason=>{ console.log(reason); })
-
中断promise链
有且只有一个方式:返回状态为pending的promise对象let p = new Promise((resolve,reject)=>{ setTimeout(() => { resolve('ok') }, 2000); }) p.then(value=>{ console.log('111'); // 有且只有一个方式 返回pending状态的promise对象 下面的.then就不会执行了 return new Promise(()=>{}) }).then(value=>{ console.log('222'); }).then(value=>{ console.log('333'); }).catch(reason=>{ console.log(reason); })
async 与 await
- async函数
函数的返回值为promise对象
promise对象的结果由async函数执行的返回值决定
- await函数
await右侧的表达式一般为promise对象,但也可以是其他值
如果表达式是promise对象。await返回的是promise成功的值
如果表达式是其他值,直接讲此值作为await的返回值
- 注意
await必须写在async函数中,但ssync函数中可以没有await
如果await的promise失败了,就会抛出异常,需要通过try…catch捕获处理
const fs = require('fs')
const util = require('util')
const mineReadFile = util.promisify(fs.readFile)
// 回调函数的方式都区三个文件拼接
// fs.readFile('./resource/content.txt',(err,data1)=>{
// if(err) throw err
// fs.readFile('./resource/c1.txt',(err,data2)=>{
// if(err) throw err
// fs.readFile('./resource/c2.txt',(err,data3)=>{
// if(err) throw err
// console.log(data1+data2+data3);
// })
// })
// })
// async与await
async function a() {
try {
let d1 = await mineReadFile('./resource/content.txt')
let d2 = await mineReadFile('./resource/c1.txt')
let d3 = await mineReadFile('./resource/c2.txt')
console.log(d1 + d2 + d3);
} catch (e) {
console.log(e);
}
}
a()