Appearance
认识Promise
Promise 是异步编程的一种解决方案: 从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。 promise有三种状态:pending(等待态),fulfiled(成功态),rejected(失败态) ;状态一旦改变,就不会再变。创造promise实例后,它会立即执行。
我相信大家经常写这样的代码:
// 当参数a大于10且参数fn2是一个方法时 执行fn2
function fn1(a, fn2) {
if (a > 10 && typeof fn2 == 'function') {
fn2()
}
}
fn1(11, function() {
console.log('this is a callback')
})复制代码// 当参数a大于10且参数fn2是一个方法时 执行fn2
function fn1(a, fn2) {
if (a > 10 && typeof fn2 == 'function') {
fn2()
}
}
fn1(11, function() {
console.log('this is a callback')
})复制代码一般来说我们会碰到的回调嵌套都不会很多,一般就一到两级,但是某些情况下,回调嵌套很多时,代码就会非常繁琐,会给我们的编程带来很多的麻烦,这种情况俗称——回调地狱。
这时候我们的promise就应运而生、粉墨登场了
promise是用来解决两个问题的:
- 回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象
- promise可以支持多个并发的请求,获取并发请求中的数据
- 这个promise可以解决异步的问题,本身不能说promise是异步的
Promise API
Promise对象是一个构造函数,用来生成Promise实例的,自身拥有着我们平时用的all、resolve、reject等熟悉的方法,原型上有着then、catch等一样熟悉的的方法。
new Promise
Promise的构造函数接收一个参数:函数,并且这个函数需要传入两个参数:
resolve :异步操作执行成功后的回调函数
reject:异步操作执行失败后的回调函数
说走就走,让我们来new一个Promise实例吧
js
let p = new Promise((resolve, reject) => {
console.log("青年野味new了一个Promise")
resolve("我成功了")
//reject('我失败了');
});
//resolve时
console.log("p",p) //p Promise {<fulfilled>: '我成功了'}
//reject时
console.log("p",p) //p Promise {<rejected>: '我失败了'},控制台会抛出一个错误
//同时执行resolve和reject时
console.log("p",p) //p Promise {<fulfilled>: '我成功了'}
// throw时
let p2 = new Promise((resolve, reject) => { throw('我报错了') })let p = new Promise((resolve, reject) => {
console.log("青年野味new了一个Promise")
resolve("我成功了")
//reject('我失败了');
});
//resolve时
console.log("p",p) //p Promise {<fulfilled>: '我成功了'}
//reject时
console.log("p",p) //p Promise {<rejected>: '我失败了'},控制台会抛出一个错误
//同时执行resolve和reject时
console.log("p",p) //p Promise {<fulfilled>: '我成功了'}
// throw时
let p2 = new Promise((resolve, reject) => { throw('我报错了') })根据上面的情况我们总结一下:
创造promise实例后,它会立即执行。
当执行了
resolve,Promise状态会变成fulfilled,即成功状态执行了
reject,Promise状态会变成rejected,即失败状态当
resolve和reject同时存在时,Promise只以第一次为准,第一次成功就永久为fulfilled,第一次失败就永远状态为rejected,状态一旦改变,就不会再变。当Promise中有
throw的话,就相当于执行了reject
那么我们就把这个四种情况一一实现了。
js
class yw_Promise {
constructor(executor) {
//默认状态为padding
this.state = "pending"
this.result = null
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
const resolve = (data) => {
if (this.state !== "pending") return
this.state = "fulfiled"
this.result = data
//当我们数组里边没有时就不用去执行
while (this.onResolvedCallbacks.length) {
this.onResolvedCallbacks.shift()(data)
}
}
const reject = (data) => {
if (this.state !== "pending") return
this.state = "rejected"
this.result = data
//当我们数组里边没有时就不用去执行
while (this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()(data)
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
}
const yw_p = new yw_Promise((resolve, reject) => {
// resolve("初次见面,成功了")
// reject("初次见面,失败了")
throw("初次见面,失败了")
})
console.log(yw_p) //yw_Promise {state: 'rejected', result: '初次见面,失败了'}class yw_Promise {
constructor(executor) {
//默认状态为padding
this.state = "pending"
this.result = null
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
const resolve = (data) => {
if (this.state !== "pending") return
this.state = "fulfiled"
this.result = data
//当我们数组里边没有时就不用去执行
while (this.onResolvedCallbacks.length) {
this.onResolvedCallbacks.shift()(data)
}
}
const reject = (data) => {
if (this.state !== "pending") return
this.state = "rejected"
this.result = data
//当我们数组里边没有时就不用去执行
while (this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()(data)
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
}
const yw_p = new yw_Promise((resolve, reject) => {
// resolve("初次见面,成功了")
// reject("初次见面,失败了")
throw("初次见面,失败了")
})
console.log(yw_p) //yw_Promise {state: 'rejected', result: '初次见面,失败了'}then
then是为 Promise 实例添加状态改变时的回调函数。前面说过,then方法的第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数,它们都是可选的。then方法返回的是一个新的Promise实例。
平时我们使用then是这样的:
js
//立即输出"OK"
let p = new Promise((resolve, reject) => {
resolve('OK');
}).then(value => console.log(value) , (err) => console.error(err) );;
// 1秒后输出 ERROR
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('ERROR')
}, 1000)
}).then(res => console.log(res), err => console.log(err))
// 链式调用 输出 20
let p3 = new Promise((resolve, reject) => {
resolve(10)
}).then(res => 2 * res, err => console.log(err))
.then(res => console.log(res), err => console.log(err))//立即输出"OK"
let p = new Promise((resolve, reject) => {
resolve('OK');
}).then(value => console.log(value) , (err) => console.error(err) );;
// 1秒后输出 ERROR
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('ERROR')
}, 1000)
}).then(res => console.log(res), err => console.log(err))
// 链式调用 输出 20
let p3 = new Promise((resolve, reject) => {
resolve(10)
}).then(res => 2 * res, err => console.log(err))
.then(res => console.log(res), err => console.log(err))我们来总结一下上面的知识点:
then函数中有两个回调参数,一个是成功的回调,一个是失败的回调- 当Promise状态为
fulfilled执行成功回调,为rejected执行失败回调 - 当
reject或者resolve在定时器中时,则等定时器执行完才再执行then then链式调用时,下一次then执行时受上一次then返回值的影响
根据上面的知识点,我们一一来实现吧
js
class yw_Promise {
...
then(onResolved, onRejected){
if(this.state === "fulfiled"){
onResolved(this.value)
}
if(this.state === "rejected"){
onRejected(this.value)
}
}
}class yw_Promise {
...
then(onResolved, onRejected){
if(this.state === "fulfiled"){
onResolved(this.value)
}
if(this.state === "rejected"){
onRejected(this.value)
}
}
}以为就这样就完了吗?那就大错特错了,上面都没有考虑到定时器和链式调用的情况呢,首先定时器情况是异步的,又因为我们需要等定时器执行完then方法才会执行,我们可以来详细看下这个定时器时候Promise的状态。
js
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
console.log("同步输出p",p) //同步输出p Promise {<pending>}
setTimeout(()=>{
console.log("异步输出p",p) //异步输出p Promise {<fulfilled>: 'OK'}
},2000)let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
console.log("同步输出p",p) //同步输出p Promise {<pending>}
setTimeout(()=>{
console.log("异步输出p",p) //异步输出p Promise {<fulfilled>: 'OK'}
},2000)当我们同步的时候发现Promise的状态还是pending,到了2秒后我们再输出就变成了fulfilled状态了。
那么问题就来我怎么知道它到底是什么时候变成了fulfilled状态?其实很简单,看定时器首先是不是要跑完,跑完了是不是要定时器里边的resolve或者是reject,这两个我们在constructor中写的是同步的吧,这两个一执行我们是不是就可以把状态改成相应的状态了,那状态肯定就不是pending,而是fulfilled或者rejected
由此then中判断如果Promise状态是pending,那这时候我们可以把每次调用resolve的结果存入一个数组中,每次调用reject的结果存入一个数组。
到这里还是很好理解的,但是在后面这一步的时候就有点难懂了。假设我现在存了有两个数组分别是onResolvedCallbacks、onRejectedCallbacks,我们的定时器也到点要跑完了,这时候要去执行一开始里边写的resolve('OK');,那你是不是要把之前存进去的回调结果一一执行了,那要怎么执行呢,从后面开始执行还是从前面开始执行。正确答案是从数组的下标0开始一一执行,因为我们要有先后顺序的排队依次出来。
根据上面说的我们来完善一下
js
class yw_Promise {
constructor(executor) {
//默认状态为padding
this.state = "padding"
this.result = undefined
//存放成功的回调
this.onResolvedCallbacks = []
//存放失败的回调
this.onRejectedCallbacks = []
const resolve = (data) => {
if (this.state !== "padding") return
this.state = "fulfiled"
this.result = data
//当我们数组里边没有时就不用去执行
while (this.onResolvedCallbacks.length) {
this.onRejectedCallbacks.shift()(data)
}
}
const reject = (data) => {
if (this.state !== "padding") return
this.state = "rejected"
this.result = data
//当我们数组里边没有时就不用去执行
while (this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()(data)
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
then(onFulFilled, onRejected) {
if (this.state === "fulfiled") {
onResolved(this.result)
}
if (this.state === "rejected") {
onRejected(this.result)
}
// 当前既没有完成 也没有失败
if (this.state === 'pending') {
// 存放成功的回调
this.onResolvedCallbacks.push(() => {
onFulFilled(this.result);
});
// 存放失败的回调
this.onRejectedCallbacks.push(() => {
onRejected(this.result);
});
}
}
}class yw_Promise {
constructor(executor) {
//默认状态为padding
this.state = "padding"
this.result = undefined
//存放成功的回调
this.onResolvedCallbacks = []
//存放失败的回调
this.onRejectedCallbacks = []
const resolve = (data) => {
if (this.state !== "padding") return
this.state = "fulfiled"
this.result = data
//当我们数组里边没有时就不用去执行
while (this.onResolvedCallbacks.length) {
this.onRejectedCallbacks.shift()(data)
}
}
const reject = (data) => {
if (this.state !== "padding") return
this.state = "rejected"
this.result = data
//当我们数组里边没有时就不用去执行
while (this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()(data)
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
then(onFulFilled, onRejected) {
if (this.state === "fulfiled") {
onResolved(this.result)
}
if (this.state === "rejected") {
onRejected(this.result)
}
// 当前既没有完成 也没有失败
if (this.state === 'pending') {
// 存放成功的回调
this.onResolvedCallbacks.push(() => {
onFulFilled(this.result);
});
// 存放失败的回调
this.onRejectedCallbacks.push(() => {
onRejected(this.result);
});
}
}
}又以为这就完了,那你有错了,还有链式调用和定时器的情况呢,一样举个简单的例子给大家做介绍
js
let p = new Promise((resolve, reject) => {
resolve('OK');
}).then(value => {
// console.log(value)
return new Promise((resolve, reject) => {
resolve("success");
});
},err=>console.error(err)).then(value => {
console.log(value);
},err=>console.error(err)).then(value => {
console.log(value);
},err=>console.error(err))
setTimeout(()=>{
console.log("p",p) //p Promise {<fulfilled>: undefined}
},2000)
console.log("p",p)
//p Promise {<pending>}
//这里为什么会输出状态pending呢,原因是then是微任务let p = new Promise((resolve, reject) => {
resolve('OK');
}).then(value => {
// console.log(value)
return new Promise((resolve, reject) => {
resolve("success");
});
},err=>console.error(err)).then(value => {
console.log(value);
},err=>console.error(err)).then(value => {
console.log(value);
},err=>console.error(err))
setTimeout(()=>{
console.log("p",p) //p Promise {<fulfilled>: undefined}
},2000)
console.log("p",p)
//p Promise {<pending>}
//这里为什么会输出状态pending呢,原因是then是微任务根据上面的例子我们总结一下知识点:
then方法本身会返回一个新的Promise对象
如果返回值是Promise对象,返回值为成功,新promise就是成功,返回值为失败,新Promise就是失败
如果返回值非Promise对象,新promise对象就是成功,值为此返回值
根据上面的总结的知识点,完善一下then
js
class yw_Promise {
....
then(onFulFilled, onRejected) {
//防止值得穿透
onFulFilled = typeof onFulFilled === 'function' ? onFulFilled : y => y;
onRejected = typeof onRejected === 'function' ? onRejected : err => {
throw err;
}
//作为下一次then方法的promise
let promise2 = new yw_Promise((resolve, reject) => {
const resolvePromise = resultCallback => {
setTimeout(() => {
try {
const x = resultCallback(this.result)
if (x === promise2) {
//不能自己等待自己完成
return reject(new TypeError('循环引用'));
}
if (x instanceof yw_Promise) {
x.then(resolve, reject)
} else {
// 非Promise就直接成功
resolve(x)
}
} catch (err) {
// 处理报错
reject(err)
}
})
}
if (this.state === "fulfiled") {
resolvePromise(onFulFilled)
}
if (this.state === "rejected") {
resolvePromise(onRejected)
}
// 当前既没有完成 也没有失败
if (this.state === 'pending') {
// 存放成功的回调
this.onResolvedCallbacks.push(() =>
resolvePromise(onFulFilled)
);
// 存放失败的回调
this.onRejectedCallbacks.push(() =>
resolvePromise(onRejected)
);
}
})
return promise2
}
}class yw_Promise {
....
then(onFulFilled, onRejected) {
//防止值得穿透
onFulFilled = typeof onFulFilled === 'function' ? onFulFilled : y => y;
onRejected = typeof onRejected === 'function' ? onRejected : err => {
throw err;
}
//作为下一次then方法的promise
let promise2 = new yw_Promise((resolve, reject) => {
const resolvePromise = resultCallback => {
setTimeout(() => {
try {
const x = resultCallback(this.result)
if (x === promise2) {
//不能自己等待自己完成
return reject(new TypeError('循环引用'));
}
if (x instanceof yw_Promise) {
x.then(resolve, reject)
} else {
// 非Promise就直接成功
resolve(x)
}
} catch (err) {
// 处理报错
reject(err)
}
})
}
if (this.state === "fulfiled") {
resolvePromise(onFulFilled)
}
if (this.state === "rejected") {
resolvePromise(onRejected)
}
// 当前既没有完成 也没有失败
if (this.state === 'pending') {
// 存放成功的回调
this.onResolvedCallbacks.push(() =>
resolvePromise(onFulFilled)
);
// 存放失败的回调
this.onRejectedCallbacks.push(() =>
resolvePromise(onRejected)
);
}
})
return promise2
}
}注意:因为实际上的then是个微任务,但这里手写的then方法实际上是一个异步的宏任务来的,因为本人自己无法实现真正意义上的微任务,就这样写了一个setTimeout来代替,如果各位大佬有什么好的建议的,带带弟弟。
以上then方法就算是完成了,但实际上如果你自己所定义的Promise需要和别人的Promise进行交互时,上面的resolvePromise就需要重写。方法中传入四个参数,分别是promise2,x,resolve,reject,promise2指的是上一次返回的promise,x表示运行promise返回的结果,resolve和reject是promise2的方法。则代码写为:
js
function resolvePromise(promise2, x, resolve, reject) {
//判断x是不是promise
//规范中规定:我们允许别人乱写,这个代码可以实现我们的promise和别人的promise 进行交互
if (promise2 === x) { //不能自己等待自己完成
return reject(new TypeError('循环引用了'));
};
// x是除了null以外的对象或者函数
if (x != null && (typeof x === 'object' || typeof x === 'function')) {
let called; //防止成功后调用失败
try { //防止取then是出现异常 object.defineProperty
let then = x.then; //取x的then方法 {then:{}}
if (typeof then === 'function') { //如果then是函数就认为他是promise
//call第一个参数是this,后面的是成功的回调和失败的回调
then.call(x, y => { //如果Y是promise就继续递归promise
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject)
}, r => { //只要失败了就失败了
if (called) return;
called = true;
reject(r);
});
} else { //then是一个普通对象,就直接成功即可
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e)
}
} else { //x = 123 x就是一个普通值 作为下个then成功的参数
resolve(x)
}
}
//then中使用可以交互的resolvePromise方法
then(){
...
if (this.state === "fulfiled") {
let x = onFulFilled(this.result);
resolvePromise(promise2,x,resolve,reject)
}
if (this.state === "rejected") {
let x = onRejected(this.result);
resolvePromise(promise2,x,resolve,reject)
}
// 当前既没有完成 也没有失败
if (this.state === 'pending') {
// 存放成功的回调
this.onResolvedCallbacks.push(() => {
let x = onFulFilled(this.result);
return resolvePromise(promise2,x,resolve,reject)
});
// 存放失败的回调
this.onRejectedCallbacks.push(() => {
let x = onRejected(this.result);
return resolvePromise(promise2,x,resolve,reject)
});
}
}function resolvePromise(promise2, x, resolve, reject) {
//判断x是不是promise
//规范中规定:我们允许别人乱写,这个代码可以实现我们的promise和别人的promise 进行交互
if (promise2 === x) { //不能自己等待自己完成
return reject(new TypeError('循环引用了'));
};
// x是除了null以外的对象或者函数
if (x != null && (typeof x === 'object' || typeof x === 'function')) {
let called; //防止成功后调用失败
try { //防止取then是出现异常 object.defineProperty
let then = x.then; //取x的then方法 {then:{}}
if (typeof then === 'function') { //如果then是函数就认为他是promise
//call第一个参数是this,后面的是成功的回调和失败的回调
then.call(x, y => { //如果Y是promise就继续递归promise
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject)
}, r => { //只要失败了就失败了
if (called) return;
called = true;
reject(r);
});
} else { //then是一个普通对象,就直接成功即可
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e)
}
} else { //x = 123 x就是一个普通值 作为下个then成功的参数
resolve(x)
}
}
//then中使用可以交互的resolvePromise方法
then(){
...
if (this.state === "fulfiled") {
let x = onFulFilled(this.result);
resolvePromise(promise2,x,resolve,reject)
}
if (this.state === "rejected") {
let x = onRejected(this.result);
resolvePromise(promise2,x,resolve,reject)
}
// 当前既没有完成 也没有失败
if (this.state === 'pending') {
// 存放成功的回调
this.onResolvedCallbacks.push(() => {
let x = onFulFilled(this.result);
return resolvePromise(promise2,x,resolve,reject)
});
// 存放失败的回调
this.onRejectedCallbacks.push(() => {
let x = onRejected(this.result);
return resolvePromise(promise2,x,resolve,reject)
});
}
}catch
catch其实本身就是一个then方法来的,只不过只有reject回调参数,resolve是undefined
js
//catch 方法
catch (onRejected) {
return this.then(undefined, onRejected);
}//catch 方法
catch (onRejected) {
return this.then(undefined, onRejected);
}resolve和reject
这里的resolve和reject并非是构造函数中接收的参数,但是跟接收参数中异步操作成功后的回调有着很相似的作用。
让我们来看一下,它们是怎么用的:
js
//第一种:
let p1 = Promise.resolve("青年野味来搞Primise了")
console.log("p1",p1) //p1 Promise {<fulfilled>: '青年野味来搞Primise了'}
//第二种:
let p2 = Promise.resolve(new Promise((resolve, reject) => {
// resolve('OK');
reject('Error');
}));
//reject时
console.log("p2",p2); //p2 Promise {<rejected>: 'Error'}
//resolve时
console.log("p2",p2); //p2 Promise {<fulfilled>: 'OK'}//第一种:
let p1 = Promise.resolve("青年野味来搞Primise了")
console.log("p1",p1) //p1 Promise {<fulfilled>: '青年野味来搞Primise了'}
//第二种:
let p2 = Promise.resolve(new Promise((resolve, reject) => {
// resolve('OK');
reject('Error');
}));
//reject时
console.log("p2",p2); //p2 Promise {<rejected>: 'Error'}
//resolve时
console.log("p2",p2); //p2 Promise {<fulfilled>: 'OK'}resolve和reject方法中,当我们使用时分两种情况:
如果传入的参数为非Promise类型的对象, 则返回的结果为相应状态的promise对象
(resolve为fulfilled状态,reject为rejected状态)如果传入的参数为 Promise 对象, 则参数的结果决定了 resolve 的结果
那让我们一起实现第一种情况先
js
//class中的静态方法
static resolve(data) {
return new yw_Promise((resolve, reject) => resolve(data))
}
static reject(data) {
return new yw_Promise((resolve, reject) => reject(data))
}
//class中的静态方法
static resolve(data) {
return new yw_Promise((resolve, reject) => resolve(data))
}
static reject(data) {
return new yw_Promise((resolve, reject) => reject(data))
}第二种情况当我们参数是Promise呢,如果使用上面的,结果里面就会返回一个Promise,所以我们要将上面的代码完善一下。
js
//完整版
//class中的静态方法
static resolve(value) {
return new yw_Promise((resolve, reject) => {
if (value instanceof yw_Promise) {
value.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//状态设置为成功
resolve(value);
}
});
}
static reject(value) {
return new yw_Promise((resolve, reject) => {
if (value instanceof yw_Promise) {
value.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//状态设置为成失败
reject(value);
}
});
}//完整版
//class中的静态方法
static resolve(value) {
return new yw_Promise((resolve, reject) => {
if (value instanceof yw_Promise) {
value.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//状态设置为成功
resolve(value);
}
});
}
static reject(value) {
return new yw_Promise((resolve, reject) => {
if (value instanceof yw_Promise) {
value.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//状态设置为成失败
reject(value);
}
});
}resolve和reject方法也就算完成了,也是跟then方法一样,并不能跟别人的Promise做交互的。因为都用了instanceof,举个例子: A instanceOf B,判断A是否经过B的原型链。因为别人的Promise并不在我们自己写的Promise原型链的,所以判断结果都是false的,有兴趣的朋友可以自己研究一下。
all
想要有很多的朋友在开发中都会遇到,我有多个接口要发请求,但是我想依次按顺序进行发送请求,这个时候就可以用到all方法
让我们来看看他的用法
js
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
return new Promise((resolve,reject)=>resolve(id));
});
Promise.all(promises).then(function (posts) {
console.log(posts) // [2, 3, 5, 7, 11, 13]
}).catch(function(reason){
// ...
});
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
if(id !== 3) return new Promise((resolve,reject)=>resolve(id));
return new Promise((resolve,reject)=>reject(id))
});
Promise.all(promises).then(function (posts) {
//...
}).catch(function(reason){
console.log(reason) //3
});
const promises = [2, 3, 5, 7, 11, 13]
Promise.all(promises).then(function (posts) {
console.log(posts) //[2, 3, 5, 7, 11, 13]
}).catch(function(reason){
console.log(reason) //此处并没有输出
});
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
return new Promise((resolve,reject)=>resolve(id));
});
Promise.all(promises).then(function (posts) {
console.log(posts) // [2, 3, 5, 7, 11, 13]
}).catch(function(reason){
// ...
});
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
if(id !== 3) return new Promise((resolve,reject)=>resolve(id));
return new Promise((resolve,reject)=>reject(id))
});
Promise.all(promises).then(function (posts) {
//...
}).catch(function(reason){
console.log(reason) //3
});
const promises = [2, 3, 5, 7, 11, 13]
Promise.all(promises).then(function (posts) {
console.log(posts) //[2, 3, 5, 7, 11, 13]
}).catch(function(reason){
console.log(reason) //此处并没有输出
});根据上面的我们来总结一下知识点:
- 如果所有Promise都成功,则返回成功结果数组
- 如果有一个Promise失败,则返回这个失败结果
- 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
那就让我们来实现一下吧
js
//添加 all 方法
static all(promises) {
//返回结果为promise对象
return new yw_Promise((resolve, reject) => {
//声明变量
let count = 0;
let arr = [];
//遍历
for (let i = 0; i < promises.length; i++) {
if (promises[i] instanceof yw_Promise) {
promises[i].then(v => {
//得知对象的状态是成功
//每个promise对象 都成功
count++;
//将当前promise对象成功的结果 存入到数组中
arr[i] = v;
//判断
if (count === promises.length) {
//修改状态
resolve(arr);
}
}, r => {
reject(r);
});
}
}
});
}
//添加 all 方法
static all(promises) {
//返回结果为promise对象
return new yw_Promise((resolve, reject) => {
//声明变量
let count = 0;
let arr = [];
//遍历
for (let i = 0; i < promises.length; i++) {
if (promises[i] instanceof yw_Promise) {
promises[i].then(v => {
//得知对象的状态是成功
//每个promise对象 都成功
count++;
//将当前promise对象成功的结果 存入到数组中
arr[i] = v;
//判断
if (count === promises.length) {
//修改状态
resolve(arr);
}
}, r => {
reject(r);
});
}
}
});
}race
- 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
- 哪个Promise最快得到结果,就返回那个结果,无论成功失败
js
//添加 race 方法
static race(promises) {
return new yw_Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
if (promises[i] instanceof yw_Promise) {
promises[i].then(v => {
//修改返回对象的状态为 『成功』
resolve(v);
}, r => {
//修改返回对象的状态为 『失败』
reject(r);
})
}
}
});
}//添加 race 方法
static race(promises) {
return new yw_Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
if (promises[i] instanceof yw_Promise) {
promises[i].then(v => {
//修改返回对象的状态为 『成功』
resolve(v);
}, r => {
//修改返回对象的状态为 『失败』
reject(r);
})
}
}
});
}allSettled
- 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
- 把每一个Promise的结果,集合成数组,返回
js
static allSettled(promises) {
return new yw_Promise((resolve, reject) => {
//声明变量
let count = 0;
let arr = [];
const addData = (status, value, i) => {
arr[i] = {
status,
value
}
count++
if (count === promises.length) {
resolve(arr)
}
}
//遍历
for (let i = 0; i < promises.length; i++) {
if (promises[i] instanceof MyPromise) {
promises[i].then(v => {
addData('fulfilled', v, i)
}, r => {
addData('rejected', r, i)
});
} else {
addData('fulfilled', promises[i], i)
}
}
});
}static allSettled(promises) {
return new yw_Promise((resolve, reject) => {
//声明变量
let count = 0;
let arr = [];
const addData = (status, value, i) => {
arr[i] = {
status,
value
}
count++
if (count === promises.length) {
resolve(arr)
}
}
//遍历
for (let i = 0; i < promises.length; i++) {
if (promises[i] instanceof MyPromise) {
promises[i].then(v => {
addData('fulfilled', v, i)
}, r => {
addData('rejected', r, i)
});
} else {
addData('fulfilled', promises[i], i)
}
}
});
}any
any与all相反
- 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
- 如果有一个Promise成功,则返回这个成功结果
- 如果所有Promise都失败,则报错
js
static any(promises) {
return new Promise((resolve, reject) => {
let count = 0
for (let i = 0; i < promises.length; i++) {
promises[i].then(val => {
resolve(val)
}, err => {
count++
if (count === promises.length) {
reject(new AggregateError('All promises were rejected'))
}
})
}
})
}static any(promises) {
return new Promise((resolve, reject) => {
let count = 0
for (let i = 0; i < promises.length; i++) {
promises[i].then(val => {
resolve(val)
}, err => {
count++
if (count === promises.length) {
reject(new AggregateError('All promises were rejected'))
}
})
}
})
}自定义Promise完整代码,细品
js
class yw_Promise {
constructor(executor) {
//默认状态为padding
this.state = "pending"
this.result = null
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
const resolve = (data) => {
if (this.state !== "pending") return
this.state = "fulfiled"
this.result = data
//当我们数组里边没有时就不用去执行
while (this.onResolvedCallbacks.length) {
this.onResolvedCallbacks.shift()(data)
}
}
const reject = (data) => {
if (this.state !== "pending") return
this.state = "rejected"
this.result = data
//当我们数组里边没有时就不用去执行
while (this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()(data)
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
then(onFulFilled, onRejected) {
//防止值得穿透
onFulFilled = typeof onFulFilled === 'function' ? onFulFilled : y => y;
onRejected = typeof onRejected === 'function' ? onRejected : err => {
throw err;
}
//作为下一次then方法的promise
let promise2 = new yw_Promise((resolve, reject) => {
const resolvePromise = resultCallback => {
setTimeout(() => {
try {
const x = resultCallback(this.result)
if (x === promise2) {
//不能自己等待自己完成
return reject(new TypeError('循环引用了'));
}
if (x instanceof yw_Promise) {
x.then(resolve, reject)
} else {
// 非Promise就直接成功
resolve(x)
}
} catch (err) {
// 处理报错
reject(err)
}
})
}
if (this.state === "fulfiled") {
resolvePromise(onFulFilled)
}
if (this.state === "rejected") {
resolvePromise(onRejected)
}
// 当前既没有完成 也没有失败
if (this.state === 'pending') {
// 存放成功的回调
this.onResolvedCallbacks.push(() =>
resolvePromise(onFulFilled)
);
// 存放失败的回调
this.onRejectedCallbacks.push(() =>
resolvePromise(onRejected)
);
}
})
return promise2
}
//catch 方法
catch (onRejected) {
return this.then(undefined, onRejected);
}
//class中的静态方法
static resolve(value) {
return new yw_Promise((resolve, reject) => {
if (value instanceof yw_Promise) {
value.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//状态设置为成功
resolve(value);
}
});
}
static reject(value) {
return new yw_Promise((resolve, reject) => {
if (value instanceof yw_Promise) {
value.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//状态设置为成功
reject(value);
}
});
}
//添加 all 方法
static all(promises) {
//返回结果为promise对象
return new yw_Promise((resolve, reject) => {
//声明变量
let count = 0;
let arr = [];
//遍历
for (let i = 0; i < promises.length; i++) {
if (promises[i] instanceof MyPromise) {
promises[i].then(v => {
//得知对象的状态是成功
//每个promise对象 都成功
count++;
//将当前promise对象成功的结果 存入到数组中
arr[i] = v;
//判断
if (count === promises.length) {
//修改状态
resolve(arr);
}
}, r => {
reject(r);
});
}
}
});
}
//添加 race 方法
static race(promises) {
return new yw_Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
if (promises[i] instanceof MyPromise) {
promises[i].then(v => {
//修改返回对象的状态为 『成功』
resolve(v);
}, r => {
//修改返回对象的状态为 『失败』
reject(r);
})
}
}
});
}
static allSettled(promises) {
return new yw_Promise((resolve, reject) => {
//声明变量
let count = 0;
let arr = [];
const addData = (status, value, i) => {
arr[i] = {
status,
value
}
count++
if (count === promises.length) {
resolve(arr)
}
}
//遍历
for (let i = 0; i < promises.length; i++) {
if (promises[i] instanceof MyPromise) {
promises[i].then(v => {
addData('fulfilled', v, i)
}, r => {
addData('rejected', r, i)
});
} else {
addData('fulfilled', promises[i], i)
}
}
});
}
static any(promises) {
return new Promise((resolve, reject) => {
let count = 0
for (let i = 0; i < promises.length; i++) {
promises[i].then(val => {
resolve(val)
}, err => {
count++
if (count === promises.length) {
reject(new AggregateError('All promises were rejected'))
}
})
}
})
}
}class yw_Promise {
constructor(executor) {
//默认状态为padding
this.state = "pending"
this.result = null
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
const resolve = (data) => {
if (this.state !== "pending") return
this.state = "fulfiled"
this.result = data
//当我们数组里边没有时就不用去执行
while (this.onResolvedCallbacks.length) {
this.onResolvedCallbacks.shift()(data)
}
}
const reject = (data) => {
if (this.state !== "pending") return
this.state = "rejected"
this.result = data
//当我们数组里边没有时就不用去执行
while (this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()(data)
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
then(onFulFilled, onRejected) {
//防止值得穿透
onFulFilled = typeof onFulFilled === 'function' ? onFulFilled : y => y;
onRejected = typeof onRejected === 'function' ? onRejected : err => {
throw err;
}
//作为下一次then方法的promise
let promise2 = new yw_Promise((resolve, reject) => {
const resolvePromise = resultCallback => {
setTimeout(() => {
try {
const x = resultCallback(this.result)
if (x === promise2) {
//不能自己等待自己完成
return reject(new TypeError('循环引用了'));
}
if (x instanceof yw_Promise) {
x.then(resolve, reject)
} else {
// 非Promise就直接成功
resolve(x)
}
} catch (err) {
// 处理报错
reject(err)
}
})
}
if (this.state === "fulfiled") {
resolvePromise(onFulFilled)
}
if (this.state === "rejected") {
resolvePromise(onRejected)
}
// 当前既没有完成 也没有失败
if (this.state === 'pending') {
// 存放成功的回调
this.onResolvedCallbacks.push(() =>
resolvePromise(onFulFilled)
);
// 存放失败的回调
this.onRejectedCallbacks.push(() =>
resolvePromise(onRejected)
);
}
})
return promise2
}
//catch 方法
catch (onRejected) {
return this.then(undefined, onRejected);
}
//class中的静态方法
static resolve(value) {
return new yw_Promise((resolve, reject) => {
if (value instanceof yw_Promise) {
value.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//状态设置为成功
resolve(value);
}
});
}
static reject(value) {
return new yw_Promise((resolve, reject) => {
if (value instanceof yw_Promise) {
value.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//状态设置为成功
reject(value);
}
});
}
//添加 all 方法
static all(promises) {
//返回结果为promise对象
return new yw_Promise((resolve, reject) => {
//声明变量
let count = 0;
let arr = [];
//遍历
for (let i = 0; i < promises.length; i++) {
if (promises[i] instanceof MyPromise) {
promises[i].then(v => {
//得知对象的状态是成功
//每个promise对象 都成功
count++;
//将当前promise对象成功的结果 存入到数组中
arr[i] = v;
//判断
if (count === promises.length) {
//修改状态
resolve(arr);
}
}, r => {
reject(r);
});
}
}
});
}
//添加 race 方法
static race(promises) {
return new yw_Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
if (promises[i] instanceof MyPromise) {
promises[i].then(v => {
//修改返回对象的状态为 『成功』
resolve(v);
}, r => {
//修改返回对象的状态为 『失败』
reject(r);
})
}
}
});
}
static allSettled(promises) {
return new yw_Promise((resolve, reject) => {
//声明变量
let count = 0;
let arr = [];
const addData = (status, value, i) => {
arr[i] = {
status,
value
}
count++
if (count === promises.length) {
resolve(arr)
}
}
//遍历
for (let i = 0; i < promises.length; i++) {
if (promises[i] instanceof MyPromise) {
promises[i].then(v => {
addData('fulfilled', v, i)
}, r => {
addData('rejected', r, i)
});
} else {
addData('fulfilled', promises[i], i)
}
}
});
}
static any(promises) {
return new Promise((resolve, reject) => {
let count = 0
for (let i = 0; i < promises.length; i++) {
promises[i].then(val => {
resolve(val)
}, err => {
count++
if (count === promises.length) {
reject(new AggregateError('All promises were rejected'))
}
})
}
})
}
}拓展
有想了解跟多Promise相关Api的可以去这里看
结语
过程总是令人烦恼的,但是结果总是出乎意外的令人的兴奋。希望这个可以帮助到大家,觉得不错的可以点赞加收藏,觉得其中写的有问题的也可以在下方评论区告诉我,让我们一直在进步的路上