手写promise
//把promise封装成一个类
class Promise{
//构造函数
constructor(executor){
//添加属性
this.PromiseState='pending';
this.PromiseResult=null;
//声明属性
this.callbacks=[];
//保存实例对象的this的值
const self=this;
//resolve函数
function resolve(data){
//判断状态 保证状态只能更改一次
if(self.PromiseState!=='pending') return;
// console.log(self);
//1.修改对象的状态(promiseState)
self.PromiseState='fulfilled';//resolved
//2.设置对象的结果值(promiseResult)
self.PromiseResult=data;
//调用成功的回调函数
setTimeout(()=>{
self.callbacks.forEach(item=>{
item.onResolved(data);
});
});
}
//reject函数
function reject(data){
//判断状态 保证状态只能更改一次
if(self.PromiseState!=='pending') return;
//1.修改对象的状态(promiseState)
self.PromiseState='rejected';//resolved
//2.设置对象的结果值(promiseResult)
self.PromiseResult=data;
//调用失败的回调函数
setTimeout(()=>{
self.callbacks.forEach(item=>{
item.onRejected(data);
});
})
}
try{
//同步调用 执行器函数
executor(resolve,reject);
}catch(e){
//修改 promise对象的状态为失败
reject(e);
}
}
//then方法封装
then(onResolved,onRejected){
const self=this;
//判断回调函数参数是否传值,允许catch上面的不传onRejected回调函数,定义默认的,允许第二个参数不传
if(typeof onRejected !== 'function'){
onRejected=reason=>{
throw reason;
}
}
//允许第一个参数不传
if(typeof onResolved !== 'function'){
onResolved=value=>value;
}
return new Promise((resolve,reject)=>{
//封装函数 三个状态的代码除了回调都一样,封装后期好维护
function callback(type){
try{
//获取回调函数的执行结果
let result=type(self.PromiseResult);
//判断
if(result instanceof Promise){
//如果是promise类型的对象
//这个result指的是index.html的return的new promise
result.then(v=>{
resolve(v);
},r=>{
reject(r);
})
}else{
//结果的对象状态为成功
resolve(result);
}
}catch(e){
reject(e);
}
}
//调用回调函数
if(this.PromiseState==='fulfilled'){
setTimeout(()=>{
callback(onResolved);
})
}
if(this.PromiseState==='rejected'){
setTimeout(()=>{
callback(onRejected);
})
}
//判断pending状态
if(this.PromiseState==='pending'){
///保存回调函数
this.callbacks.push({
onResolved: function(){
callback(onResolved);
},
onRejected: function(){
callback(onRejected);
}
});
}
})
}
//catch方法
catch(onRejected){
return this.then(undefined,onRejected);
}
//resolve方法不属于实例对象,属于类,构造函数
static resolve(value){
//返回promise对象
return new Promise((resolve,reject)=>{
if(value instanceof Promise){
value.then(v=>{
resolve(v);
},r=>{
reject(r);
})
}else{
resolve(value);
}
})
}
//reject
static reject(reason){
//返回一个失败的promise对象
return new Promise((resolve,reject)=>{
reject(reason);
})
}
//添加all方法
static all(promises) {
//返回结果为promise对象
return new Promise((resolve,reject)=>{
//声明变量,记录有几个promise对象成功
let count=0;
//声明数组,记录每个成功的peomise对象的
let arr=[];
//遍历
for(let i=0;i<promises.length;i++){
//
promises[i].then(v=>{
//得知对象的状态是成功
//所有的promise对象都成功
count++;
//将当前promise对象成功的结果存到数组中
arr[i]=v;
if(count===promises.length){
resolve(arr);
}
},r=>{
reject(r);
})
}
})
}
//添加race方法
static race(promises){
//返回结果是promise对象
return new Promise((resolve,reject)=>{
for(let i=0;i<promises.length;i++){
//哪个状态先改变哪个就决定结果
promises[i].then(v=>{
//修改返回对象的状态为成功
resolve(v);
},r=>{
//修改返回对象的状态为失败
reject(r);
})
}
})
}
}
// //声明构造函数
// function Promise(executor){
// //添加属性
// this.PromiseState='pending';
// this.PromiseResult=null;
// //声明属性
// this.callbacks=[];
// //保存实例对象的this的值
// const self=this;
// //resolve函数
// function resolve(data){
// //判断状态 保证状态只能更改一次
// if(self.PromiseState!=='pending') return;
// // console.log(self);
// //1.修改对象的状态(promiseState)
// self.PromiseState='fulfilled';//resolved
// //2.设置对象的结果值(promiseResult)
// self.PromiseResult=data;
// //调用成功的回调函数
// setTimeout(()=>{
// self.callbacks.forEach(item=>{
// item.onResolved(data);
// });
// });
// }
// //reject函数
// function reject(data){
// //判断状态 保证状态只能更改一次
// if(self.PromiseState!=='pending') return;
// //1.修改对象的状态(promiseState)
// self.PromiseState='rejected';//resolved
// //2.设置对象的结果值(promiseResult)
// self.PromiseResult=data;
// //调用失败的回调函数
// setTimeout(()=>{
// self.callbacks.forEach(item=>{
// item.onRejected(data);
// });
// })
// }
// try{
// //同步调用 执行器函数
// executor(resolve,reject);
// }catch(e){
// //修改 promise对象的状态为失败
// reject(e);
// }
// }
// //添加then方法
// Promise.prototype.then=function(onResolved,onRejected){
// const self=this;
// //判断回调函数参数是否传值,允许catch上面的不传onRejected回调函数,定义默认的,允许第二个参数不传
// if(typeof onRejected !== 'function'){
// onRejected=reason=>{
// throw reason;
// }
// }
// //允许第一个参数不传
// if(typeof onResolved !== 'function'){
// onResolved=value=>value;
// }
// return new Promise((resolve,reject)=>{
// //封装函数 三个状态的代码除了回调都一样,封装后期好维护
// function callback(type){
// try{
// //获取回调函数的执行结果
// let result=type(self.PromiseResult);
// //判断
// if(result instanceof Promise){
// //如果是promise类型的对象
// //这个result指的是index.html的return的new promise
// result.then(v=>{
// resolve(v);
// },r=>{
// reject(r);
// })
// }else{
// //结果的对象状态为成功
// resolve(result);
// }
// }catch(e){
// reject(e);
// }
// }
// //调用回调函数
// if(this.PromiseState==='fulfilled'){
// setTimeout(()=>{
// callback(onResolved);
// })
// }
// if(this.PromiseState==='rejected'){
// setTimeout(()=>{
// callback(onRejected);
// })
// }
// //判断pending状态
// if(this.PromiseState==='pending'){
// ///保存回调函数
// this.callbacks.push({
// onResolved: function(){
// callback(onResolved);
// },
// onRejected: function(){
// callback(onRejected);
// }
// });
// }
// })
// }
// //添加catch方法
// Promise.prototype.catch=function(onRejected){
// return this.then(undefined,onRejected);
// }
// //添加resolve方法
// Promise.resolve=function(value){
// //返回promise对象
// return new Promise((resolve,reject)=>{
// if(value instanceof Promise){
// value.then(v=>{
// resolve(v);
// },r=>{
// reject(r);
// })
// }else{
// resolve(value);
// }
// })
// }
// //添加reject方法
// Promise.reject=function(reason){
// //返回一个失败的promise对象
// return new Promise((resolve,reject)=>{
// reject(reason);
// })
// }
// //添加all方法
// Promise.all=function (promises) {
// //返回结果为promise对象
// return new Promise((resolve,reject)=>{
// //声明变量,记录有几个promise对象成功
// let count=0;
// //声明数组,记录每个成功的peomise对象的
// let arr=[];
// //遍历
// for(let i=0;i<promises.length;i++){
// //
// promises[i].then(v=>{
// //得知对象的状态是成功
// //所有的promise对象都成功
// count++;
// //将当前promise对象成功的结果存到数组中
// arr[i]=v;
// if(count===promises.length){
// resolve(arr);
// }
// },r=>{
// reject(r);
// })
// }
// })
// }
// //添加race方法
// Promise.race=function(promises){
// //返回结果是promise对象
// return new Promise((resolve,reject)=>{
// for(let i=0;i<promises.length;i++){
// //哪个状态先改变哪个就决定结果
// promises[i].then(v=>{
// //修改返回对象的状态为成功
// resolve(v);
// },r=>{
// //修改返回对象的状态为失败
// reject(r);
// })
// }
// })
// }
async 和 await
async函数
-
函数的返回值是promise对象
-
promise对象的结果由async函数执行的返回值决定
//和then方法返回结果的规则是一样的 async function main() { //1.如果返回值是一个非promise类型的数据 // return 521; //2.如果返回的是一个proise对象 // return new Promise((resolve,reject)=>{ // // resolve('ok'); // reject('error') // }) //3.抛出异常 throw "fail"; } let result=main(); console.log(result);
await表达式
-
await右侧的表达式一般为promise对象,但也可以是其他的值
-
如果表达式是promise对象,await返回的是promise成功的值
-
如果表达式是其他值,直接将此值作为await的返回值
async function main(){ let p=new Promise((resolve,reject)=>{ // resolve('ok'); reject("error"); }) // //1.右侧为promise的情况 // let res=await p; // console.log(res); // //2.右侧为其他类型的数据 // let res2=await 20; // console.log(res2); //2.如果promise是失败的状态,要用try catch拿到失败的结果 try{ let res3=await p; }catch(e){ console.log(e); } } main();
注意
- await必须写在async函数中,但async函数中可以没有await
- 如果await的promise失败了,就会抛出异常,需要通过try…catch捕获处理
async与await结合实践:
/**
* 读取resource文件夹下 1.html 2.html 3.html文件内容
*/
const fs=require('fs');
const util=require('util');
const mineReadFile=util.promisify(fs.readFile);//可以把这些api转成promise形态的函数
//回调函数的方式
// fs.readFile('./resource/1.html',(err,data1)=>{
// if(err) throw err;
// fs.readFile('./resource/2.html',(err,data2)=>{
// if(err) throw err;
// fs.readFile('./resource/3.html',(err,data3)=>{
// if(err) throw err;
// console.log(data1+data2+data3);
// })
// })
// })
//async和await
async function main(){
try{
//读取第一个文件内容
let data1=await mineReadFile('./resource/1.html');
let data2=await mineReadFile('./resource/2.html');
let data3=await mineReadFile('./resource/3.html');
console.log(data1+data2+data3);
}catch(e){
console.log(e.code);
}
}
main();
async与await结合发送AJAX请求:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="btn">点击获取段子</button>
<script>
function sendAJAX(url, method = 'GET', data = null) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(method, url, true);
// 设置请求头,如果是POST请求且发送的数据是JSON
if (method === 'POST' && data) {
xhr.setRequestHeader('Content-Type', 'application/json');
}
// 注册状态变化事件处理程序
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status >= 200 && xhr.status < 300) {
// 请求成功,解析响应并解析Promise
try {
const response = JSON.parse(xhr.responseText);
resolve(response);
} catch (e) {
resolve(xhr.responseText);
}
} else {
// 请求失败,拒绝Promise
reject(new Error(`Request failed with status code ${xhr.status}`));
}
}
};
// 处理网络错误
xhr.onerror = function () {
reject(new Error('Network error'));
};
// 发送请求
if (method === 'POST' && data) {
xhr.send(JSON.stringify(data));
} else {
xhr.send();
}
});
}
let btn=document.querySelector('#btn');
btn.addEventListener('click',async function(){
let data=await sendAJAX('https://jsonplaceholder.typicode.com/posts');
console.log(data);
})
</script>
</body>
</html>