前端基础知识---Promise
1 promimse的介绍
promise 是异步编程的新解决方案
异步编程:
fs 文件操作
ajax数据库
定时器
回调函数与promise的区别:
(1)promise支持链式调用,可以解决回调地狱问题
(2)更灵活
2 随机中奖案例
<body><div class="container"><h2 class="page-header">Promise初体验</h2><button class="btn btn-primary" id="btn">点击抽奖</button></div><script>//生成随机数function rand(m,n){return Math.ceil(Math.random()*(n-m+1))+m-1}// 获取元素对象
const btn = document.querySelector('#btn');
// 绑定单击事件
btn.addEventListener('click', function() {// promise实现异步操作(局部变量p)const p = new Promise((res, rej) => {setTimeout(() => {let n = rand(1, 100);if (n <= 30) res(n);else rej(n);}, 1000);});// 在这里调用then,确保能访问到pp.then((value) => alert('恭喜中奖,'+'你的中奖号码是'+value),(reason) => alert('再接再厉,'+'你的号码是'+reason));
});
3 读取文件案例
注意:读出来的是buffer格式,所以需要toString转成字符串格式
const fs = require('fs')
let p = new Promise((res,rej)=>{fs.readFile('./resource/text.txt',(err,data)=>{if(err) rej(err)res(data)})
})//调用then
p.then(value=>{console.log(value.toString())
},reason=>{console.log(reason)})4 promise 封装和风格化( 风格化减少了封装步骤)
封装:
//封装一个函数读取文件内容
function mineReadFile(path){return new Promise((res,rej)=>{//读取文件require('fs').readFile(path,(err,data)=>{if(err) rej(err)res(data)})})
}mineReadFile('./resource/text.txt')
.then(value=>{//输出文件内容console.log(value.toString());
},reason=>{console.log(reason)
}
)
风格化:
const util = require('util')
const fs = require('fs')
let mineReadFile = util.promisify(fs.readFile)
mineReadFile('./resource/text.txt').then(value=>{console.log(value.toString())
})5 promise对象属性
状态属性 PromiseState
pending 未决定的
resolved / fullfilled 成功
rejected 失败
状态只会从pending转到其他两种属性
值属性 PromiseState
resolve
reject
无论成功与失败,这两个值都被保存
工作流程:

6 promise的关键问题
Promise 的 .then() 回调有个核心特性:它会 “等待” 前一个 Promise 完成后才执行。
7 自定义封装
7.1 resolve和reject
Promise.resolve(value) 的核心逻辑是将任意值(包括 Promise 实例)转换为一个 Promise 对象,并根据 value 的类型决定最终状态:
Promise.reject(reason) 的逻辑很简单:不管 reason 是什么(不管是不是 Promise),直接返回一个 “失败状态” 的 Promise。
//添加resolve方法
Promise.resolve = function(value){//返回promise对象return new Promise((res,rej)=>{if(value instanceof Promise){value.then(v=>{res(v)},r=>{rej(r)})}else{//状态设置成功res(value)}})
}//添加reject方法
Promise.reject = function(reason){return new Promise((res,rej)=>{rej(reason)})
}7.2 all方法
//添加all方法
Promise.all = function(promises){//返回结果是promise对象return new Promise((res,rej)=>{//声明变量let count = 0let arr = []for(let i=0; i<promises.length;i++){promises[i].then(v=>{count++; //promise对象状态是成功则count+1arr[i]=v //将当前promise对象成功的结果存入到数组中if(count === promises.length){//修改状态res(arr)}},r=>{rej(r)})}})
}7.3 race方法
//添加race方法
Promise.race =function(promises){return new Promise((res,rej)=>{for(let i=0;i<promises.length;i++){promises[0].then(v=>{//修改返回对象的状态为成功res(v)},r=>{rej(r)})}})
}7.4 then方法的异步回调执行(添加计时器)
//调用成功的回调函数setTimeout(()=>{self.callback.forEach(item=>{item.onResolved(data)})})// 3. 执行失败回调(遍历callback数组,调用onRejected)setTimeout(()=>{self.callback.forEach(item => {item.onRejected(data);});})7.5 封装
resolve不是实例对象,属于类(构造函数用static)
8 Async与await
8.1 async函数
(1)函数返回值为promise对象
(2)promise返回对象的结果由async函数执行的返回值决定(类似then方法)
8.2 await表达式
await 只能跟 Promise 对象 配合使用。
(1)await右侧的表达式一般为promise对象,但也可以是其他的值
(2)如果表达式是promise对象,await返回的是promise成功的值
(3)如果表达式是其他值,直接将此值作为await的返回值
8.3 async和await的结合
const fs = require('fs').promises;// 正确实现异步读取函数
async function mineReadFile(path) {return await fs.readFile(path, 'utf8'); // 指定编码为 utf8
}async function main(){try{//读取第一个文件的内容let data1 = await mineReadFile('./resource/1.txt')let data2 = await mineReadFile('./resource/2.txt')let data3 = await mineReadFile('./resource/3.txt')console.log(data1 + data2 + data3)}catch(e){}}
main()