前言
Promise 是一种异步解决方案,没有Promise的时候,异步方案就是回调函数,嵌套多了就会陷入回调地狱。以下旨在讲核心用法及实现。
1、promise 的 then
“
then
方法的第一个参数是resolved
状态的回调函数,第二个参数(可选)是rejected
状态的回调函数。then
方法返回的是一个新的Promise
实例(注意,不是原来那个Promise
实例)。因此可以采用链式写法,即then
方法后面再调用另一个then
方法。- then方法的回调函数的返回值,会作为参数,再传给then方法返回的这个Promise实例的resolve
- 采用链式的
then
,可以指定一组按照次序调用的回调函数。这时,前一个回调函数,有可能返回的还是一个Promise
对象(即有异步操作),这时后一个回调函数,就会等待该Promise
对象的状态发生变化,才会被调用。 - 如果Promise对象 返回的结果是reject,then不会被执行,会走到catch里
“
// then---demo1---针对上面第二点
new Promise((resolve, reject) => {
resolve(100); // resolve--> Promise对像由 Pending状态变为 onFulfilled 状态
}).then(data => {
console.log(data); // 100
return 'adf' // then 方法返回新的Promise实例,也就是说即使不return值,后面的then方法也会执行
})
.then(data => {
console.log(data) // 上面返回了固定值,所以直接resolve掉 输出 adf
})
// then---demo2---针对上面第三点
function wait(ms = 1000, data) { // 返回一个Promise对象,并在ms时间之后 resolve(data)
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data)
},ms)
})
}
const promise = new Promise((resolve, reject) => {
resolve(100);
}).then(data => {
console.log(data); // 100
return wait(2000, 'qwe');
})
.then(data => {
console.log(data); // 2秒之后 qwe
})
const promise = new Promise((resolve, reject) => {
reject('some error')
}).then(data => {
console.log(data); // 不执行
}).catch(e => {
console.log(e) // some error
})
复制代码
2、async await 语法糖
函数前面加上 async 就会返回Promise对象,所以就可以用then语法
// async---demo1
function wait(ms = 1000, data) { // 返回一个Promise对象,并在ms时间之后 resolve(data)
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data)
},ms)
})
}
async function foo(){
console.log('begin');
const w1 = await wait(1000, 'w1');
console.log('target1');
const w2 = await wait(2000, 'w2');
console.log('target2');
}
foo().then(data => {
console.log('finished', data) // data 是undefined 因为上面的async 函数没有return,resolve的结果就为undefined
})
复制代码
如果async函数里 出现了 reject,就相当于在Promise 里出现了reject,有catch会捕获,没有catch会抛错
function wait(ms = 1000, data) { // 返回一个Promise对象,并在ms时间之后 resolve(data)
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data)
},ms)
})
}
async function bar(){
console.log('begin');
const w1 = await wait(1000, 'w1');
console.log('target1');
const w2 = await wait(2000, 'w2');
const x = await Promise.reject('some error'); // await 不能忘
}
bar().then(d => console.log(d)); // 出错
bar().catch(e => console.log(e)); // 可以catch到error
async function bar(){
try{
console.log('begin');
const w1 = await wait(1000, 'w1');
console.log('target1');
const w2 = await wait(2000, 'w2');
const x = Promise.reject('some error');
} catch(ex) {
console.log(ex, 'js捕获语法同样可以捕获')
}
}
复制代码
3、并发和竞争
// 模拟异步的wait函数
function wait(ms = 1000, data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data);
}, ms)
})
}
// Promise.all 数组里的每个异步都成功,返回一个数组
Promise.all([wait(2000, 1), wait(3000,2)]).then(data => {
console.log(data); // [1,2]
})
// Promise.race 返回最先回来的结果
Promise.race([wait(2000, 1), wait(3000, 2)]).then(data => {
console.log(data) //
})
复制代码
4、Promise 核心实现
// 有三个状态 这是三个变量
const PENDING = 1;
const FULFILLED = 2;
const REJETED = 3;
class myPromise {
constructor(excutor) {
this.state = PENDING; // 初始化就是pending 状态
// 这个resolver 经常放到异步函数里执行,也就是会延迟执行
const resolver = (value) => {
if(this.state === PENDING) {
this.value = value; // resolve之后,把参数给到this.value
this.state = FULFILLED; // 执行resolver后 状态改变
}
// 在then里 Pending态的时候,数组里存进去了值,所以可以正常延迟执行这里
for(let [onFulfilled, resolve] of this.fulfills) {
const x = onFulfilled(this.value);
// 这里没有做完善处理,比如如果x如果也是个Promise,待完善
// 注意:这个resolve是在循环里边的,当前fulfilles里是只有一个元素,并且始终也只会有一个,
// 因为即使 使用.then().then().then()的写法,每次执行then里的resove才能继续项后.then,而在
// .then的时候,就像现在,已经执行完了当前循环。
resolve(x);
}
}
const rejector = (value) => {
}
excutor(resolver, rejector); // 传入的构造函数,第一时间就会执行,Promise执行机制
// 为处理异步做准备
this.fulfills = [];
}
then(onFulfilled) { //原型上的方法 相当于 Promise.prototype.then
return new myPromise((resolve, reject) => { // 返回一个新的Promsie
switch(this.state) {
case FULFILLED:
const x = onFulfilled(this.value); // 执行外部传入的onFulfilled方法,通过this.value 取值
resolve(x); // 对then返回的Promise 执行resolve,并传入x,这个x是onFulfilled的返回值
break;
case PENDING: // 如果处于pending态,说明excutor里有异步方法,使用存放操作
this.fulfills.push([onFulfilled, resolve]); // 执行到这里先存入数组
break;
}
})
}
}
new myPromise((resolve, reject) => {
//测试异步
// setTimeout(() => {
// resolve(200)
// }, 1000)
resolve(100); // resovle的参数,会传给this.value
return 'abc' // 这个return的值 后面的then没有接收,
}).then(data => { // 这个入参是 this.value
console.log(data); // 100
return 'sdf' // then方法返回了个Promise实例,它接收的回调函数的返回值 会再传到这个Promise的resolve里
}).then(d => console.log(d)) // sdf
复制代码
5、Promise 主要功能实现
Promise A+规范要求
/*
* Promise 的实现 主要两个大块,一个是then,一个是resolvePromise
*
*/
const statusMap = {
PENDING: 'pending',
FULFULLED: 'fulfilled',
REJECTED: 'rejected'
}
function fulfilledPromise(promise, value) {
// 只能从pending状态转换为其他状态
if (promise.status !== statusMap.PENDING) {
return
}
promise.value = value; // 改变值为 resolve传进来的值
promise.status = statusMap.FULFILLED; // 改变状态
runCbs(promise.fulfilledCbs, value);
}
function rejectedPromise(promise, reason) {
// 只能从pending状态转换为其他状态
if (this.status !== statusMap.PENDING) {
return
}
promise.value = reason
promise.status = statusMap.REJECTED;
runCbs(promise.rejectedCbs, reason);
}
function runCbs(cbs, value) {
cbs.forEach(cb => cb(value))
}
function isFunc(fn) {
return (
Object.prototype.toString.call(fn).toLowerCase() === '[object function]'
);
}
function isPromise(p) {
return p instanceof ourPromise;
}
function isObject(obj) {
return (
Object.prototype.toString.call(obj).toLowerCase() === '[object object]'
);
}
// promise 的解析
function resolvePromise(promise, x) {
// x和promise相同(会出现循环调用)
if (promise === x) {
rejectedPromise(promise, new TypeError('cant be the same'));
return
}
// x 是promise
if (isPromise(x)) {
if (x.status === statusMap.FUlFILLED) {
fulfilledPromise(promise, x.value);
return
}
if (x.status === statusMap.REJECTED) {
rejectedPromise(promise, x.reason);
return;
}
if (x.status === statusMap.PENDING) {
x.then(() => {
fulfilledPromise(promise, x.value);
}, () => {
rejectedPromise(promise, x.reason);
});
return;
}
}
// x 是对象或者函数
if (isObject(x) || isFunc(x)) {
let then;
let called = false;
try {
then = x.then;
} catch (errot) {
rejectedPromise(promise, error);
return
}
if (isFunc(then)) {
// then 是 参数上的then,外部传进来的 不受控制,所以加try cahtch
try {
then.call(x, (y) => {
if (called) {
return
}
called = true;
resolvePromise(promise, y);
}, (r) => {
if (called) {
return
}
called = true;
rejectedPromise(promise, r)
});
} catch (e) {
if (called) {
return
}
called = true;
rejectedPromise(promise, e)
}
} else {
fulfilledPromise(promise, x);
return;
}
// x 不是对象或者函数
} else {
fulfilledPromise(promise, x);
}
}
class ourPromise {
constructor(fn) {
this.status = statusMap.PENDING; // 初始态的是pending
this.value = undefined; // 传参用的变量
this.reason = undefined; // 失败的拒因
this.fulfilledCbs = [];
this.rejectedCbs = [];
fn((value) => { // 构造函数的执行
fulfilledPromise(this, value); // this 是指Promise实例,
}, (reason) => {
rejectedPromise(this, reason);
});
}
then(onFulfilled, onRejected){
const promise1 = this; // 保存一个当前的promise 实例
const promise2 = new ourPromise(() => { }) // 将返回的新promise实例
// Fulfilled 状态处理
if (promise1.status === statusMap.FULFILLED) {
// 异常判断,如果then的入参不是函数,就忽略,返回promise1
if (!isFunc(onFulfilled)) {
return promise1
}
// 模拟异步,同步任务执行完成后再执行
setTimeout(() => {
try {
const x = onFulfilled(promise1.value);
resolvePromise(promise2, x); // 决议promise2的状态
} catch (e) {
rejectedPromise(promise2, e);
}
}, 0)
}
// Rejected 状态处理
if (promise1.status === statusMap.REJECTED) {
// 异常判断,如果then的入参不是函数,就忽略,返回promise1
if (!isFunc(onRejected)) {
return promise1
}
// 模拟异步,同步任务执行完成后再执行
setTimeout(() => {
try {
const x = onRejected(promise1.value);
resolvePromise(promise2, x); // 决议promise2的状态
} catch (e) {
rejectedPromise(promise2, e);
}
}, 0)
}
// Pending 状态处理
if (promise1.status === statusMap.PENDING) {
onFulfilled = isFunc(onFulfilled) ? onFulfilled : (value) => value;
onRejected = isFunc(onRejected) ? onRejected : (err) => {throw err};
promise1.fulfilledCbs.push(
() => {
setTimeout(() => {
try {
const x = onFulfilled(promise1.value);
resolvePromise(promise2, x); // 决议promise2的状态
} catch (e) {
rejectedPromise(promise2, e);
}
}, 0)
}
);
promise1.rejectedCbs.push(
() => {
setTimeout(() => {
try {
const x = onRejected(promise1.reason);
resolvePromise(promise2, x); // 决议promise2的状态
} catch (e) {
rejectedPromise(promise2, e);
}
}, 0);
}
);
}
return promise2 // 返回一个新的promise实例
}
}
// test
function wait (ms = 1000, data) {
return new ourPromise ((resolve, rejected) => {
setTimeout(() => {
resolve(data)
}, 0)
})
}
const promise1 = new ourPromise((resolve, rejected) => {
console.log('start')
resolve(122);
}).then(data => {
console.log(data)
return wait(1000, '哈哈哈')
}).then(d => console.log(d, 'dddd'))
// promise-aplus 测试用例钩子
// ourPromise.deferred = function () {
// const deferred = {};
// deferred.promise = new ourPromise((resolve, rejected) => {
// deferred.resolve = resolve;
// deferred.rejected = rejected;
// })
// return deferred;
// }
// module.exports = ourPromise;
复制代码
6、小结
简单说,Promise 最主要的就是两大块
- then的实现,
then
方法返回的是一个新的Promise
实例 - 决议状态resolvePromise
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END