一步一步实现自己的Promise,CSS全局样式的设置

console.log(“onResolved:”,value);

},

reason=>{

console.log(“onRejected:”,reason);

}

)

3. 实现then方法


尽人皆知的时,执行到then时,promise可能会是pending状态,此时就要把then里的回调函数保存起来,也可能会是resolved或者rejected状态,此时要执行onResolved或onRejected方法。

Promise.prototype.then = function(onResolved,onRejected){

var self = this

if(self.status === ‘pending’){

// promise当前状态还是pending状态,将回调函数保存起来

self.callbacks.push({

onResolved(){onResolved(self.data)},

onRejected(){onRejected(self.data)}

})

}else if(self.status === ‘resolved’){

setTimeout(()=>{

onResolved(self.data)

})

}else{

setTimeout(()=>{

onResolved(self.data)

})

}

}

而且我们知道,执行完then是要返回一个新的promise的,而新的promise的状态则由当前then的执行结果来确定。

Promise.prototype.then = function(onResolved,onRejected){

var self = this

return new Promise((resolve,reject)=>{

if(self.status === ‘pending’){

// promise当前状态还是pending状态,将回调函数保存起来

self.callbacks.push({

onResolved(){onResolved(self.data)},

onRejected(){onRejected(self.data)}

})

}else if(self.status === ‘resolved’){

setTimeout(()=>{

onResolved(self.data)

})

}else{

setTimeout(()=>{

onResolved(self.data)

})

}

})

}

当当前的promise状态为resolved的时候,则当前执行的onresolved函数由三种情况

  1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。

// 例5

let promise = new Promise((resolve,reject)=>{

resolve(1)

})

promise.then(

value=>{

return value

},

reason=>{

console.log(“onRejected:”,reason);

}

)

因此,我们可以这样实现

Promise.prototype.then = function(onResolved,onRejected){

var self = this

return new Promise((resolve,reject)=>{

if(self.status === ‘pending’){

// promise当前状态还是pending状态,将回调函数保存起来

self.callbacks.push({

onResolved(){onResolved(self.data)},

onRejected(){onRejected(self.data)}

})

}else if(self.status === ‘resolved’){

setTimeout(()=>{

const result = onResolved(self.data)

if (result instanceof Promise){

} else {

// 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。

resolve(result)

}

})

}else{

setTimeout(()=>{

onResolved(self.data)

})

}

})

}

  1. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果,如代码所示,我们返回一个新的promise。这个新的promise执行了resolve,因此返回的promise的状态是resolved的

// 例6

let promise = new Promise((resolve,reject)=>{

resolve(1)

})

promise.then(

value=>{

return new Promise((resolve,reject)=>{

resolve(2)

})

},

reason=>{

console.log(“onRejected:”,reason);

}

)

因此我们可以这样实现

Promise.prototype.then = function(onResolved,onRejected){

var self = this

return new Promise((resolve,reject)=>{

if(self.status === ‘pending’){

// promise当前状态还是pending状态,将回调函数保存起来

self.callbacks.push({

onResolved(){onResolved(self.data)},

onRejected(){onRejected(self.data)}

})

}else if(self.status === ‘resolved’){

setTimeout(()=>{

const result = onResolved(self.data)

if (result instanceof Promise){

// 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果

result.then(

value => {resolve(value)},

reason => {reject(reason)}

)

} else {

// 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。

resolve(result)

}

})

}else{

setTimeout(()=>{

onResolved(self.data)

})

}

})

}

在这里说明一下:

result.then(

value => {resolve(value)},

reason => {reject(reason)}

)

由于我们在例6中执行了then里的resolve函数,

将会导致value => {resolve(value)},这个回调函数的执行,因此会把即将返回的新的promise的data设置为value,会把状态设置为resolved。

  1. 如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected,我们可以用try catch来实现

setTimeout(()=>{

try{

const result = onResolved(self.data)

if (result instanceof Promise){

// 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果

result.then(

value => {resolve(value)},

reason => {reject(reason)}

)

} else {

// 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。

resolve(result)

}

}catch (e) {

// 3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected

reject(e)

}

})

异曲同工之妙的是当当status === ‘rejected’,道理一样

setTimeout(()=>{

try{

const result = onRejected(self.data)

if (result instanceof Promise){

// 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果

result.then(

value => {resolve(value)},

reason => {reject(reason)}

)

} else {

// 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。

resolve(result)

}

}catch (e) {

// 3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected

reject(e)

}

})

到这里,我们发现当执行resolve的时候,onResolved(self.data)onRejected(self.data)执行时也会跟上面一样的结果,可以说执行回调函数都要做以上判断,因此我们要将

self.callbacks.push({

onResolved(){onResolved(self.data)},

onRejected(){onRejected(self.data)}

})

改成

if(self.status === ‘pending’){

// promise当前状态还是pending状态,将回调函数保存起来

self.callbacks.push({

onResolved(){

try{

const result = onResolved(self.data)

if (result instanceof Promise){

// 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果

result.then(

value => {resolve(value)},

reason => {reject(reason)}

)

} else {

// 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。

resolve(result)

}

}catch (e) {

// 3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected

reject(e)

}

},

到此,我们发现,相同的代码太多了,因此有必要封装一下

function handle(callback) {

try{

const result = callback(self.data)

if (result instanceof Promise){

// 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果

result.then(

value => {resolve(value)},

reason => {reject(reason)}

)

} else {

// 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。

resolve(result)

}

}catch (e) {

// 3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected

reject(e)

}

}

这样以来就清爽了很多

Promise.prototype.then = function(onResolved,onRejected){

var self = this

return new Promise((resolve,reject)=>{

/*

调用指定回调函数的处理,根据执行结果。改变return的promise状态

*/

function handle(callback) {

try{

const result = callback(self.data)

if (result instanceof Promise){

// 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果

result.then(

value => {resolve(value)},

reason => {reject(reason)}

)

} else {

// 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。

resolve(result)

}

}catch (e) {

// 3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected

reject(e)

}

}

if(self.status === ‘pending’){

// promise当前状态还是pending状态,将回调函数保存起来

self.callbacks.push({

onResolved(){

handle(onResolved)

},

onRejected(){

handle(onRejected)

}

})

}else if(self.status === ‘resolved’){

setTimeout(()=>{

handle(onResolved)

})

}else{ // 当status === ‘rejected’

setTimeout(()=>{

handle(onRejected)

})

}

})

}

另外,我们还知道,promise会发生直传透,例如

Promise.resolve(1)

.then(2)

.then(Promise.resolve(3))

.then(console.log)

运行结果: 1

解释:.then 或者 .catch 的参数期望是函数,传入非函数则会发生值穿透。值传透可以理解为,当传入then的不是函数的时候,这个then是无效的。

因此,要实现直传透这个特性,我们可以这样实现

添加这两句来判断要不要发生值传透

onResolved = typeof onResolved === ‘function’? onResolved: value => value

onRejected = typeof onRejected === ‘function’? onRejected: reason => {throw reason}

Promise.prototype.then = function(onResolved,onRejected){

onResolved = typeof onResolved === ‘function’? onResolved: value => value

onRejected = typeof onRejected === ‘function’? onRejected: reason => {throw reason}

var self = this

return new Promise((resolve,reject)=>{

/*

调用指定回调函数的处理,根据执行结果。改变return的promise状态

*/

function handle(callback) {

try{

const result = callback(self.data)

if (result instanceof Promise){

// 2. 如果回调函数返回的是promise,return的promise的结果就是这个promise的结果

result.then(

value => {resolve(value)},

reason => {reject(reason)}

)

} else {

// 1. 如果回调函数返回的不是promise,return的promise的状态是resolved,value就是返回的值。

resolve(result)

}

}catch (e) {

// 3.如果执行onResolved的时候抛出错误,则返回的promise的状态为rejected

reject(e)

}

}

if(self.status === ‘pending’){

// promise当前状态还是pending状态,将回调函数保存起来

self.callbacks.push({

onResolved(){

handle(onResolved)

},

onRejected(){

handle(onRejected)

}

})

}else if(self.status === ‘resolved’){

setTimeout(()=>{

handle(onResolved)

})

}else{ // 当status === ‘rejected’

setTimeout(()=>{

handle(onRejected)

})

}

})

}

3.实现catch方法


妇孺皆知的是,catch方法的作用跟then里的第二歌回调函数一样,因此我们可以这样来实现

Promise.prototype.catch = function(onRejected){

return this.then(undefined,onRejected)

}

天啊,居然这么简单

4. 实现Promise.resolve


我们都知道,Promise.resolve方法可以传三种值

  1. 不是promise

  2. 成功状态的promise

  3. 失败状态的promise

Promise.resolve(1)

Promise.resolve(Promise.resolve(1))

Promise.resolve(Promise.reject(1))

实际上跟实现上面的then时有点像

Promise.resolve = function(value){

return new Promise((resolve,reject)=>{

if (value instanceof Promise){

// 如果value 是promise

value.then(

value => {resolve(value)},

reason => {reject(reason)}

)

} else{

// 如果value不是promise

resolve(value)

}

}

}

5.实现Promise.reject


实现这个比较简单,返回一个状态为rejected的promise就好了

/*

Promise函数对象的reject方法

返回一个指定reason的失败状态的promise对象

*/

Promise.reject = function(reason){

return new Promise((resolve,reject)=>{

reject(reason)

})

}

6.实现Promise.all


我们知道,这个方法会返回一个promise

/*

Promise函数对象的all方法

返回一个promise对象,只有当所有promise都成功时返回的promise状态才成功

*/

Promise.all = function(promises){

return new Promise((resolve,reject)=>{

})

}

而这个promise的状态由遍历每个promise产生的结果决定

/*

Promise函数对象的all方法

返回一个promise对象,只有当所有promise都成功时返回的promise状态才成功

*/

Promise.all = function(promises){

return new Promise((resolve,reject)=>{

// 遍历promises,获取每个promise的结果

promises.forEach((p,index)=>{

})

})

}

有两种结果:

  1. 遍历到有一个promise是reject状态,则直接返回的promise状态为rejected

Promise.all = function(promises){

return new Promise((resolve,reject)=>{

// 遍历promises,获取每个promise的结果

promises.forEach((p,index)=>{

p.then(

value => {

},

reason => { //只要有一个失败,return的promise状态就为reject

reject(reason)

}

)

})

})

}

  1. 遍历所有的promise的状态都为resolved,则返回的promise状态为resolved,并且还要每个promise产生的值传递下去

Promise.all = function(promises){

const values = new Array(promises.length)

var resolvedCount = 0 //计状态为resolved的promise的数量

return new Promise((resolve,reject)=>{

// 遍历promises,获取每个promise的结果

promises.forEach((p,index)=>{

p.then(

value => {

// p状态为resolved,将值保存起来

values[index] = value

resolvedCount++;

// 如果全部p都为resolved状态,return的promise状态为resolved

if(resolvedCount === promises.length){

resolve(values)

}

},

reason => { //只要有一个失败,return的promise状态就为reject

reject(reason)

}

)

})

})

}

好像可以了,当其实这里还有一个问题,就是all传进去的数组不一定都是promise对象,可能是这样的

all([p,2,3,p])

因此需要把不是promise的数字包装成promise

Promise.all = function(promises){

const values = new Array(promises.length)

var resolvedCount = 0 //计状态为resolved的promise的数量

return new Promise((resolve,reject)=>{

// 遍历promises,获取每个promise的结果

promises.forEach((p,index)=>{

Promise.resolve§.then(

value => {

// p状态为resolved,将值保存起来

values[index] = value

resolvedCount++;

// 如果全部p都为resolved状态,return的promise状态为resolved

if(resolvedCount === promises.length){

resolve(values)

}

},

reason => { //只要有一个失败,return的promise状态就为reject

reject(reason)

}

)

})

})

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

更多面试题

**《350页前端校招面试题精编解析大全》**内容大纲主要包括 HTML,CSS,前端基础,前端核心,前端进阶,移动端开发,计算机基础,算法与数据结构,项目,职业发展等等

资料获取方式:点击蓝色传送门免费获取

resolved的promise的数量

return new Promise((resolve,reject)=>{

// 遍历promises,获取每个promise的结果

promises.forEach((p,index)=>{

Promise.resolve§.then(

value => {

// p状态为resolved,将值保存起来

values[index] = value

resolvedCount++;

// 如果全部p都为resolved状态,return的promise状态为resolved

if(resolvedCount === promises.length){

resolve(values)

}

},

reason => { //只要有一个失败,return的promise状态就为reject

reject(reason)

}

)

})

})

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-X8Mtev7Y-1712258857987)]

[外链图片转存中…(img-1okKQ8xO-1712258857988)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

[外链图片转存中…(img-FkqZUu6G-1712258857988)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

更多面试题

**《350页前端校招面试题精编解析大全》**内容大纲主要包括 HTML,CSS,前端基础,前端核心,前端进阶,移动端开发,计算机基础,算法与数据结构,项目,职业发展等等

资料获取方式:点击蓝色传送门免费获取

[外链图片转存中…(img-XnbZzRiK-1712258857989)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值