Promise
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理且更强大。它最早由社区提出并实现,ES6将其写进了语言标准,统一了用法,并原生提供了Promise对象。
Promise使用
const p = new Promise((resolve, reject) => {
console.log('立即执行');
resolve('成功');
});
p.then(res => {
console.log('res', res);
})
- 1 Promise 是一个构造函数
- 2 new Promise的时候传入一个执行函数,且是立即执行的
- 3 执行函数接收两个参数resolve函数, reject函数,且可以接受参数
- 4 Promise实例上有个then的方法,then方法接收两个参数
- 5 resolve函数, reject函数是内部函数
基本结构
class basicPromise {
constructor(excutor) {
let resolve = (value) => {
console.log(value);
}
let reject = (reason) => {
console.log(reason);
}
try {
excutor(resolve, reject)
} catch (error) {
throw error;
}
}
then(fn1, fn2) {
}
}
let bp = new basicPromise((resolve, reject) => {
resolve('成功');
})
bp.then(res => {
console.log('res--',res);
})
Promise 的状态
一个 promise 所处的状态必须为以下三者之一:待定(pending),兑现(fulfilled,有时候也称为 “解决”,resolved),拒绝(rejected)
-
当处于待定状态时:
- 可以流转为代表成功的兑现状态,或者代表失败的拒绝状态。
-
当处于兑现状态时:
- 不可流转到其它任何状态
- 必须拥有一个不可变的终值
-
当处于拒绝状态时:
-
不可流转到其它任何状态
-
必须拥有一个不可变的拒因
-
/*
resolve() promise的状态 pending --> fulfilled;
reject() promise的状态pending --> rejected
*/
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class basicPromise {
constructor(excutor) {
this.state = PENDING;
let resolve = (value) => {
if(this.state === PENDING) {
this.state = FULFILLED;
console.log(value);
}
}
let reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
console.log(reason);
}
}
try {
excutor(resolve, reject)
} catch (error) {
throw error;
}
}
then(fn1, fn2) {
}
}
let p1 = new basicPromise((resolve, reject) => {
resolve('成功');
})
p1.then(res => {
console.log('res--', res);
})
then 方法
一个 promise 必须提供一个 then 方法以访问其当前值或者终值或者拒因。
promise.then(onFulfilled, onRejected)
-
onFulfilled 和 onRejected 都是可选参数:
如果 onFulfilled 不是函数,必须将其忽略
如果 onRejected 不是函数,必须将其忽略
-
如果 onFulfilled 是函数:
当 promise 解决后其必须被调用,其第一个参数为 promise 的终值
在 promise 解决前其不可被调用
其调用次数不可超过一次
-
如果 onRejected 是函数:
当 promise 拒绝后其必须被调用,其第一个参数为 promise 的拒因
在 promise 拒绝前其不可被调用
其调用次数不可超过一次
-
调用时机
onFulfilled 和 onRejected 只有在执行环境堆栈仅包含平台代码时才可被调用
- 调用要求
onFulfilled 和 onRejected 必须被作为函数调用(换句话说就是:没有 this 值)
执行函数为异步函数(同步忽略)
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class basicPromise {
constructor(excutor) {
this.state = PENDING; // 状态
this.value = undefined; // 成功返回
this.reason = undefined; // 失败返回
// 异步函数存储
this.onFulfilledCallback = undefined;
this.onRejectedCallback = undefined;
let resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
this.onFulfilledCallback && this.onFulfilledCallback(value)
}
}
let reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason;
this.onRejectedCallback && this.onFulfilledCallback(reason)
}
}
try {
excutor(resolve, reject)
} catch (error) {
throw error;
}
}
then(onFulfilled, onRejected) {
if (this.state === FULFILLED) {
typeof onFulfilled === 'function' && setTimeout(() => {
onFulfilled(this.value);
}, 0)
} else if (this.state === REJECTED) {
typeof onRejected === 'function' && setTimeout(() => {
onRejected(this.reason);
}, 0)
} else {
// 执行函数为异步函数
if (typeof onFulfilled === 'function') {
this.onFulfilledCallback = (value) => setTimeout(() => {
onFulfilled(value)
}, 0)
}
if (typeof onRejected === 'function') {
this.onRejectedCallback = (reason) => setTimeout(() => {
onRejected(reason)
}, 0)
}
}
}
}
let p1 = new basicPromise((resolve, reject) => {
setTimeout(() => {
console.log('立即执行');
// resolve('成功');
reject('失败');
}, 1000)
})
p1.then(res => {
console.log('res--', res);
}, reason => {
console.log('reason', reason);
})
1 执行函数为同步函数的时候,
在 const p = new Promise(executor) 时,执行函数会立即执行,且是同步的,
那么resolve函数也是同步执行,此时promise的状态已经改变了,
value也拿到了,然后再执行p.then(onFulfilled, onRejected),
此时便可以直接判断promise的状态来执行的函数
2 执行函数为异步函数的时候
在 const p = new Promise(executor) 时,执行函数立即执行,
但是resolve函数是异步执行的,此时的promise的状态仍是待定的,
value值仍为undifined,然后再同步执行p.then(onFulfilled, onRejected),
此时可以将onFulfilled, onRejected函数保存下来(class中直接保存到this),
等到异步执行resolve函数时,在resolve函数中执行onFulfilled并传参即可,
同理reject函数中执行onRejected
then函数多次被调用
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class basicPromise {
constructor(excutor) {
this.state = PENDING; // 状态
this.value = undefined; // 成功返回
this.reason = undefined; // 失败返回
// 异步函数存储
this.onFulfilledCallbacks = []; //数组形式
this.onRejectedCallbacks = [];
let resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
this.onFulfilledCallbacks && this.onFulfilledCallbacks.forEach(resolve => {
resolve(value)
})
}
}
let reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason;
this.onRejectedCallbacks && this.onRejectedCallbacks.forEach(reject => {
reject(reason)
})
}
}
try {
excutor(resolve, reject)
} catch (error) {
throw error;
}
}
then(onFulfilled, onRejected) {
if (this.state === FULFILLED) {
typeof onFulfilled === 'function' && setTimeout(() => {
onFulfilled(this.value);
}, 0)
} else if (this.state === REJECTED) {
typeof onRejected === 'function' && setTimeout(() => {
onRejected(this.reason);
}, 0)
} else {
// 执行函数为异步函数
if (typeof onFulfilled === 'function') {
this.onFulfilledCallbacks.push((value) => setTimeout(() => {
onFulfilled(value)
}, 0))
}
if (typeof onRejected === 'function') {
this.onRejectedCallbacks.push((reason) => setTimeout(() => {
onRejected(reason)
}, 0))
}
}
}
}
let p1 = new basicPromise((resolve, reject) => {
setTimeout(() => {
console.log('立即执行');
// resolve('成功');
reject('失败');
}, 1000)
})
p1.then(res => {
console.log('res--', res);
}, reason => {
console.log('reason', reason);
})
p1.then(res => {
console.log('res--', res);
}, reason => {
console.log('reason', reason);
})
p1.then(res => {
console.log('res--', res);
}, reason => {
console.log('reason', reason);
})
then方法必须返回一个promise对象
- 如果 onFulfilled 或者 onRejected 为函数且返回一个值 x ,则运行 Promise 解决过程:[[Resolve]](promise2, x)
- 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝并返回拒因 e
- 如果 onFulfilled 不是函数且 promise1 已解决, promise2 必须解决并返回与 promise1 相同的值
- 如果 onRejected 不是函数且 promise1 已拒绝, promise2 必须拒绝并返回与 promise1 相同的拒因
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
function resolvePromise(promise, x) {
}
class basicPromise {
constructor(excutor) {
this.state = PENDING; // 状态
this.value = undefined; // 成功返回
this.reason = undefined; // 失败返回
// 异步函数存储
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
this.onFulfilledCallbacks && this.onFulfilledCallbacks.forEach(resolve => {
resolve(value)
})
}
}
let reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason;
this.onRejectedCallbacks && this.onRejectedCallbacks.forEach(reject => {
reject(reason)
})
}
}
try {
excutor(resolve, reject)
} catch (error) {
throw error;
}
}
then(onFulfilled, onRejected) {
const promise2 = new basicPromise((resolve, reject) => {
if (this.state === FULFILLED) {
if (typeof onFulfilled === 'function') {
try {
setTimeout(() => {
const x = onFulfilled(this.value);
resolvePromise(promise2, x)
}, 0)
} catch (error) {
reject(error)
}
} else {
resolve(this.value);
}
} else if (this.state === REJECTED) {
if (typeof onRejected === 'function') {
try {
setTimeout(() => {
const x = onRejected(this.reason);
resolvePromise(promise2, x)
}, 0)
} catch (error) {
reject(error)
}
} else {
reject(this.reason)
}
} else {
// 执行函数为异步函数
this.onFulfilledCallbacks.push((value) => setTimeout(() => {
if (typeof onFulfilled === 'function') {
try {
const x = onFulfilled(value)
resolvePromise(promise2, x)
} catch (error) {
reject(error)
}
} else {
resolve(value)
}
}, 0))
this.onRejectedCallbacks.push((reason) => setTimeout(() => {
if (typeof onRejected === 'function') {
try {
const x = onRejected(reason)
resolvePromise(promise2, x)
} catch (error) {
reject(error)
}
} else {
reject(reason)
}
}, 0))
}
});
return promise2
}
}
let p1 = new basicPromise((resolve, reject) => {
setTimeout(() => {
console.log('立即执行');
// resolve('成功');
reject('失败');
}, 1000)
})
then方法执行的过程
执行 [[Resolve]](promise2, x) 需遵循以下步骤:
-
x 与 promise2 相等
如果 promise2 和 x 指向同一对象,以 TypeError 为拒因拒绝 promise2
-
如果 x 为 Promise,依据状态不同:
如果 x 处于待定状态, promise2 需保持为待定状态直至 x 被解决或拒绝
如果 x 处于兑现状态,用与 x 相同的终值解决 promise2
如果 x 处于拒绝状态,用与 x 相同的拒因拒绝 promise2
-
如果 x 是一个对象或者函数
把 x.then 赋值给 then
如果取 x.then 的值时抛出错误 e ,则以 e 为拒因拒绝 promise2
如果 then 是函数,将 x 作为函数的作用域 this 调用之。传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,第二个参数叫做 rejectPromise:
如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise2, y) 如果 rejectPromise 以拒因 r 为参数被调用,则以拒因 r 拒绝 promise2 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用 -
如果调用 then 方法抛出了异常 e:
如果 resolvePromise 或 rejectPromise 已经被调用,则忽略之
否则以 e 为拒因拒绝 promise2
-
如果 then 不是函数,以 x 为参数解决 promise2
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
function resolvePromise(promise, x, resolve, reject) {
if (promise === x) { // promise2 和 x 指向同一对象,以 TypeError 为拒因拒绝 promise2
reject(new TypeError('Chaining cycle detected for promise'));
} else if (typeof x === 'function' || (typeof x === 'object' && x !== null)) { // 如果 x 是一个对象或者函数,上面第 2 点,如果 x 为 Promise,由于 Promise 也是一个对象,所以不用单独处理了
let called = false; // 是否被调用,用于处理当 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,仅首次调用并忽略剩下的调用
try {
const then = x.then;
if (typeof then === 'function') { // then 为函数
then.call(x, y => { // then 函数执行并接收两个回调函数
if (called) return;
called = true;
resolvePromise(promise, y, resolve, reject);
}, r => {
if (called) return;
called = true;
reject(r);
});
} else {
resolve(x); // 处理上述第 3 点中的第 4 点, then 不是函数,以 x 为参数解决 promise2
};
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
resolve(x); // 如果 x 不为对象或者函数,以 x 为参数解决 promise2
}
};
class basicPromise {
constructor(excutor) {
this.state = PENDING; // 状态
this.value = undefined; // 成功返回
this.reason = undefined; // 失败返回
// 异步函数存储
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
this.onFulfilledCallbacks && this.onFulfilledCallbacks.forEach(resolve => {
resolve(value)
})
}
}
let reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason;
this.onRejectedCallbacks && this.onRejectedCallbacks.forEach(reject => {
reject(reason)
})
}
}
try {
excutor(resolve, reject)
} catch (error) {
throw error;
}
}
then(onFulfilled, onRejected) {
const promise2 = new basicPromise((resolve, reject) => {
if (this.state === FULFILLED) {
if (typeof onFulfilled === 'function') {
try {
setTimeout(() => {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject)
}, 0)
} catch (error) {
reject(error)
}
} else {
resolve(this.value);
}
} else if (this.state === REJECTED) {
if (typeof onRejected === 'function') {
try {
setTimeout(() => {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject)
}, 0)
} catch (error) {
reject(error)
}
} else {
reject(this.reason)
}
} else {
// 执行函数为异步函数
this.onFulfilledCallbacks.push((value) => setTimeout(() => {
if (typeof onFulfilled === 'function') {
try {
const x = onFulfilled(value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
} else {
resolve(value)
}
}, 0))
this.onRejectedCallbacks.push((reason) => setTimeout(() => {
if (typeof onRejected === 'function') {
try {
const x = onRejected(reason)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
} else {
reject(reason)
}
}, 0))
}
});
return promise2
}
}
let p1 = new basicPromise((resolve, reject) => {
setTimeout(() => {
console.log('立即执行');
// resolve('成功');
reject('失败');
}, 1000)
})