异步操作包含哪些?
- fs 文件操作
- 数据库操作
- AJAX
- 定时器
为什么要用Promise?
Prmise支持链式调用,可以解决回调地狱问题
Promise的基本构造?
Promise是一个构造函数,声明的时候需要传入两个函数resolve,reject
当成功调用resolve(这里还能做一些操作,将会当作返回值,传送给.then(xxx))
当失败调用reject(这里也能做一些操作,将会当做返回值,传送给.catch(xxx))
promise有三种状态
pending
resolved / fullfilled
rejected
Promise有三个参数
PromiseState:用来定义状态
PromiseResult:用来返回结果
callback:用来存储多次调用then方法的异步操作
Promise的封装方法:
const p = new Promise((resolve,reject) = > {
setTimeout( () => {
let count = Math.random() * 100;
if ( n < 50) {
resolve('data-success')
} else {
reject('data-fail')
}
})
})
node自带封装好的primise === util.promisfy(func):传入func即可将func封装为promise
封装ajax
function senAJAX(url) {
return new Promise((resolve,reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET',url);
xhr.send();
//处理结果
xhr.onreadstatechange = function() {
if(xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response)
} else {
reject(xhr.status)
}
}
}
})
}
当执行器executor内部是同步操作:
let P = Promise((resolve,reject) => {
//这里是同步任务
resolve('同步')
});
P.then( value => {
//这里是异步任务
console.log(value)
})
// 执行顺序:先执行同步的resolve,返回状态,再执行.then回调
当执行器executor内部是异步操作:
let P = Promise((resolve,reject) => {
setTimeout( () => {
resolve('异步')
},1000)
});
P.then( value => {
console.log(value)
})
// 模拟正常接口请求,会产生异步请求:执行顺序: 将.then里的方法塞入回调数组内等待状态=>返回异步状态resolve=>按照顺序执行回调.then
链式回调 => 错误捕捉 => 中断链式
let P = Promise((resolve,reject) => {
setTimeout( () => {
resolve('异步')
},1000)
});
P.then( value => {
console.log(value) // '异步'
return new Promise((resolve,reject) => {
resolve('第二次返回')
})
}).then(value => {
console.log(value) // '第二次返回'
// return new Promise(() => {}) // 如果要中断,只有返回pendding状态的promise才能中断
}).then(value => {
console.log(value) // 'undefined' 因为第二次的回调函数.then并没有返回Promise,就没有返回相应的value
}).catch(err => {
console.log(err) // 最后使用一次catch能获取上没每个promise的错误信息
})
手写Promise
手写前的知识储备:
1.Promise构造函数:Promise(executor) {}
executor:执行器(resolve,reject) => {}
executor会在Promise内部立即同步调用(同步指按顺序调用)
2.Promise.prototype.then方法:(onResolved,onRejected) =>{}
Promise.prototype.catch方法:(onRejected) =>{}
3.resolve方法,Promise.resolve是函数方法而不是实例方法
当传入非promise值的时候,返回一个成功的Promise
当传入Promise的时候,Promise的状态和值决定resolve的状态和值(套娃)
4.reject方法,Promise.reject是函数的方法而不是实例方法
不管传入什么,返回都是失败的Promise
5.all方法,Promise.all(arr),成功则放回 所有Promise成功的结果组成的数组,失败则放回第一个失败的Promise返回的error,只要有一个失败就直接失败
6.race方法,Promise.race(arr),第一个返回结果的promise决定返回的状态
class promise {
//构造方法
constructor(executor) {
// 添加属性
this.PromiseState = 'pending';
this.PromiseResult = null;
// 当executor中执行异步操作,then中并没有获取到具体的状态,无法执行,所以要声明一个回调函数,保存then的回调
this.callback = []; // 可能存在一个promise多次回调.then
// 保存实例对象的this
const self = this;
// executor 获得传入的resolve,reject
// resolve函数
function resolve(data) {
if(self.PromiseState !== 'pending') return; //增加判断,让状态只能更改一次
//修改对象状态 promiseState
self.PromiseState = 'fulfilled'; //resolved
//返回对象的结果 promiseResult
self.PromiseResult = data;
setTimeout(() => {
// .then是异步操作
self.callback.forEach(element => {
element.onResolved(data)
});
});
}
// reject函数
function reject(data) {
if(self.PromiseState !== 'pending') return;
//修改对象状态 promiseState
self.PromiseState = 'rejected';
//返回对象的结果 promiseResult
self.PromiseResult = data;
setTimeout(() => {
// .then是异步操作
self.callback.forEach(element => {
element.onRejected(data)
});
});
}
try{
// 同步调用 执行器函数
executor(resolve,reject);
}catch(e){
reject(e)
}
}
then(onResolved,onRejected) {
let self = this;
// 异常穿透,多个.then却没有对reject的处理,onRejected为undefined
if (typeof onRejected !== 'function') {
onRejected = reason => {
throw reason
}
}
// 当直接.then,then内部也没有嵌套函数,则onResolved也为undefined,给个默认值
if (typeof onResolved !== 'function') {
onResolved = value => value
}
return new Promise((resolve,reject) => {
// 封装callback函数
function getcallback(type) {
try {
let result = type(self.PromiseResult);
if(result instanceof Promise) {
//如果是Promise类型的对象
result.then(v => {
resolve(v)
},r => {
reject(r)
})
}else {
resolve(result)
}
} catch (error) {
reject(error)
}
}
//给then返回Promise,以防发生套娃(在.then函数内继续嵌套Promise)
if(this.PromiseState === 'fulfilled') {
setTimeout(() => {
// .then是异步操作
getcallback(onResolved)
});
}
if(this.PromiseState === 'rejected') {
setTimeout(() => {
// .then是异步操作
getcallback(onRejected)
});
}
if(this.PromiseState === 'pending') {
//当executor中有异步操作,状态还未改变,保存回调函数
this.callback.push({
onResolved:function(){
getcallback(onResolved)
// onResolved(self.PromiseResult)
},
onRejected:function(){
getcallback(onRejected)
// onRejected(self.PromiseResult)
}
});
}
})
}
catch(onRejected) {
return this.then(undefined,onRejected)
}
static resolve(value) {
// 返回Promise对象
return new Promise((resolve,reject) => {
if(value instanceof Promise) {
value.then(v => {
resolve(v)
},r => {
reject(r)
})
} else {
// 非Promise,则修改状态,返回内容
resolve(value)
}
})
}
// 无论传入什么,都返回失败reject的Promise
static reject(reason) {
return new Promise((resolve,reject) => {
reject(reason)
})
}
// all:所有promise都成功则根据数组序列将结果塞进对应的返回结果中,然后改变状态
// 当有一个promise先返回错误后,则立马修改状态,并返回当前Promise的结果
static all(promises){
return new Promise((resolve,reject) => {
let count = 0;
let arr = [];
for(let i=0;i<promises.length;i++) {
promises[i].then( v=> {
count++;
arr[i] = v;
if (count === promises.length) {
resolve(arr)
}
},r => {
reject(r)
})
}
})
}
// race:哪个先返回结果哪个先改变状态,并返回对应的值
static race(promises){
return new Promise((resolve,reject) => {
for(let i=0;i<promises.length;i++) {
promises[i].then( v=> {
resolve(v)
},r => {
reject(r)
})
}
})
}
}
其他有趣文章的传送门:
- 初识NODE(从常用模块到小型web服务器构建)
- 一篇学会Array原型里的所有方法
- 一篇掌握Object原型里的所有方法
- 初识Vue3,带你认识Vue2和Vue3的区别(一)
- 妈妈说,不会Vue3会被人看不起的(二)
- 奇怪的原型链冷知识(需要有一定原型链的基础才能看哦)
- vue图片放大器,相册集:vue-photo-preview
- 手摸手教你从0用echart写一个响应式页面
- JS实现URL下载