Promise 是异步编程的一种解决方案
如何理解:
没有异步就不需要promise。
Promise本身不是异步,只是我们去编写异步代码的一种方式
1,声明一个Promise
首先呢,promise肯定是一个类,我们就用class来声明。
由于new Promise((resolve, reject)=>{}),所以传入一个参数(函数), promisesA+规范 里叫他executor(执行器),传入就执行。
executor里面有两个参数,一个叫resolve(成功),一个叫reject(失败)。
由于resolve和reject可执行,所以都是函数,我们用let声明。
创建一个Promise类

2,解决基本状态
promiseA+规范对Promise有规定:
Promise存在三个状态(status)pending、fulfilled、rejected
pending(等待态)为初始态,并可以转化为fulfilled(成功态)和rejected(失败态)
成功时,不可转为其他状态,且必须有一个不可改变的值(value)
失败时,不可转为其他状态,且必须有一个不可改变的原因(reason)
成功态 : new Promise((resolve,reject)=>{resolve(value)})
resolve为成功,接收参数value,状态改变为fulfilled,不可再次改变。
失败态 : new Promise((resolve, reject)=>{reject(reason)})
reject为失败,接收参数reason,状态改变为rejected,不可再次改变。
若是executor函数报错, 直接执行reject(); 既抛出一个错误:throw new Error()
**手写一个最基本的promise类**
//首先设置三个状态(status)pending、fulfilled、rejected
const PENDING = "PENDING";
const RESOLVED = "RESOLVED";
const REJECTED = "REJECTED";
class Promise {
//给创造函数中传入执行器executor
constructor(executor) {
this.status = PENDING // 初始化status为等待态
this.value = undefined //终值
this.reason = undefined //据因
let resolve = (value) => { //成功的函数
if (this.status == PENDING) {
// 储存成功的值
this.value = value
// resolve调用后,status转化为成功态
this.status = RESOLVED
}
}
let reject = (reason) => { //失败的函数
if (this.status == PENDING) {
// 储存失败的值
this.reason = reason
// reject 调用后,status转化为失败态
this.status = REJECTED
}
}
// 看有没有弹出错误
try{
//没有抛出错误,执行executor
executor(resolve,reject)
}catch(e){ //如果抛出错误,拿到抛出的数据e
reject(e) //遇到抛出错误直接执行reject
}
}
// then函数 当.then时调用
//调用then函数要传入两个函数(--(data)=>{}---(err)=>{}--),即onfulfilled(成功时调用),onrejected(失败时调用)
then(onfulfilled,onrejected){
if(this.status===RESOLVED){
// 成功态调用的函数
onfulfilled(this.value)
}
if(this.status===REJECTED){
// 失败态调用的函数
onrejected(this.reason)
}
}
}
module.exports = Promise
3,then方法
Promise规定:Promise有一个叫做then的方法,里面有两个参onFulfilled,onRejected,成功有成功的值,失败有失败的原因
当状态status为fulfilled,则执行onFulfilled,传入this.value。当状态status为rejected,则执行onRejected,传入this.reason
onFulfilled,onRejected如果他们是函数,则必须分别在fulfilled,rejected后被调用,value或reason依次作为他们的第一个参数
class Promise{
constructor(executor){...}
// then 方法 有两个参数onFulfilled onRejected
then(onFulfilled,onRejected) {
// 状态为fulfilled(即resolve),执行onFulfilled,传入成功的值
if (this.state === 'fulfilled') {
onFulfilled(this.value);
};
// 状态为rejected,执行onRejected,传入失败的原因
if (this.state === 'rejected') {
onRejected(this.reason);
};
}
}
现在基本可以实现简单的同步代码,但是当resolve在setTomeout内执行,then时state还是pending等待状态
我们就需要在then调用的时候,将成功和失败存到各自的数组,一旦reject或者resolve,就调用它们
接下来就看一下异步的解决方案
4,解决异步,完成resolvePromise函数
类似于发布订阅,先将then里面的两个函数储存起来,由于一个promise可以有多个then,所以存在同一个数组内。
// 多个then的情况
let p = new Promise();
p.then();
p.then();
成功或者失败时,forEach调用它们
const PENDING = "PENDING";
const RESOLVED = "RESOLVED";
const REJECTED = "REJECTED";
class Promise {
constructor(executor) {
this.status = PENDING
this.value = undefined //终值
this.reason = undefined //据因
// 有异步的时候才存回调函数
this.onResolvedCallbacks=[] //存成功的回调函数,相当于一个容器
this.onRejectedCallbacks=[] //存失败的回调函数,相当于一个容器
let resolve = (value) => { //成功的函数
if (this.status == PENDING) {
this.value = value
this.status = RESOLVED
//当是成功态时将onResolvedCallbacks中的函数拿出来执行
//fn表示onResolvedCallbacks中的每一项
this.onResolvedCallbacks.forEach(fn=>fn())
}
}
let reject = (reason) => { //失败的函数
if (this.status == PENDING) {
this.reason = reason
this.status = REJECTED
//当是失败态时将onRejectedCallbacks中的函数拿出来执行
//fn表示onRejectedCallbacks中的每一项
this.onRejectedCallbacks.forEach(fn=>fn())
}
}
// 看有没有弹出错误
try{
executor(resolve,reject)
}catch(e){
reject(e)
}
}
// then函数
then(onfulfilled,onrejected){
if(this.status===RESOLVED){
// 成功态调用的函数
onfulfilled(this.value)
}
if(this.status===REJECTED){
// 失败态调用的函数
onrejected(this.reason)
}
// 如果调用then的时候,状态是等待态,表示可能存在异步
if(this.status===PENDING){
// 订阅 将成功的函数放入onResolvedCallbacks容器中
this.onResolvedCallbacks.push(()=>{
onfulfilled(this.value)
})
// 订阅 将失败的函数放入onRejectedCallbacks容器中
this.onRejectedCallbacks.push(()=>{
onrejected(this.reason)
})
}
}
}
module.exports = Promise
5.**解决then的链式调用**
const PENDING = "PENDING";
const RESOLVED = "RESOLVED";
const REJECTED = "REJECTED";
// 比较promise2和x的关系
function resolvePromise(promise2, x, resolve, reject) {
// console.log(promise2)
// console.log(x)
// promise2===x相当于 let promise2 = new Promise((resolve)=>{resolve()}).then(data=>{return promise2})
//就是我在等我吃饭
if (promise2 === x) {
// 循环引用报错
return reject(new TypeError('Chaining cycle detected for promise #<Promise></Promise>'))
}
// 防止多次调用
let called;
if ((typeof x === "object" && x !== null) || typeof x === "function") {
// x是一个对象(不包含null)或是一个函数
try {
//有可能手动在x上加上一个then属性
let then = x.then
if (typeof then === "function") {
// 防止多次调用
if (called) return;
called = true
// x有then,并且是一个then函数,说明x是promise
// x是promise
// 让x调用then方法
then.call(x, y => {
// 采用promise的成功结果,向下传递
// resolve(y)
// 有可能成功的函数也返回一个promise 递归
resolvePromise(promise2, y, resolve, reject)
}, r => {
if (called) return;
called = true
// 采用promise的失败结果,向下传递
reject(r)
})
} else {
// x有then,但then不是一个函数,是一个对象
// x不是promise,是普通值
resolve(x)
}
} catch (e) {
reject(e)
}
} else {
// x就是一个普通值
resolve(x)
}
}
class Promise {
constructor(executor) {
this.status = PENDING
this.value = undefined //终值
this.reason = undefined //据因
// 有异步的时候才存回调函数
this.onResolvedCallbacks = [] //存成功的回调函数
this.onRejectedCallbacks = [] //存失败的回调函数
let resolve = (value) => { //成功的函数
if (this.status == PENDING) {
this.value = value
this.status = RESOLVED
this.onResolvedCallbacks.forEach(fn => fn())
}
}
let reject = (reason) => { //失败的函数
if (this.status == PENDING) {
this.reason = reason
this.status = REJECTED
this.onRejectedCallbacks.forEach(fn => fn())
}
}
// 看有没有弹出错误
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
// then函数
then(onfulfilled, onrejected) {
// 防止then中什么都不写
// onFulfilled如果不是函数,就忽略onFulfilled,直接返回value
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
// onRejected如果不是函数,就忽略onRejected,直接扔出错误
onRejected = typeof onRejected === 'function' ? onRejected : err => {
throw err
};
// 这里的promise2是自己写的promise
// promise2是返回的新的promise
let promise2 = new Promise((resolve, reject) => {
if (this.status === RESOLVED) {
// 因为new完之后才会得到promise2,所以这里用计时器,异步,new完后拿到promise2
setTimeout(() => {
try {
// 成功态调用的函数
// x可能是promise,也可能是普通值
// 如果是普通值,这个值就作为下一个then成功的结果
let x = onfulfilled(this.value)
// 假如x是promise(有自己的状态),需要让promise2拥有x同样的状态
// resolvePromise函数,处理promise2和x之间的关系
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
}, 0)
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
// 失败态调用的函数
let x = onrejected(this.reason)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
}, 0)
}
// 如果调用then的时候,状态是等待态,表示可能存在异步
if (this.status === PENDING) {
// 订阅
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onfulfilled(this.value)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
}, 0)
})
// 订阅
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onrejected(this.reason)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
}, 0)
})
}
})
return promise2
}
}
module.exports = Promise
6.验证我们的promise是否正确
1、先在后面加上下述代码
2、npm 有一个promises-aplus-tests插件 npm i promises-aplus-tests -g 可以全局安装 mac用户最前面加上sudo
3、命令行 promises-aplus-tests [js文件名] 即可验证
// 目前是通过他测试 他会测试一个对象 // 语法糖 Promise.defer = Promise.deferred =
function () { let dfd = {} dfd.promise = new
Promise((resolve,reject)=>{
dfd.resolve = resolve;
dfd.reject = reject; }); return dfd; } module.exports = Promise;
//npm install promises-aplus-tests 用来测试自己的promise符不符合promisesA+规范
2646

被折叠的 条评论
为什么被折叠?



