一步一步实现自己的Promise(1),前端开发网页

Promise函数对象的resovle方法

返回一个指定结果的promise对象

*/

Promise.resolve = function(value){

}

/*

Promise函数对象的reject方法

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

*/

Promise.reject = function(value){

}

/*

Promise函数对象的all方法

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

*/

Promise.all = function(value){

}

/*

Promise函数对象的race方法

返回一个promise对象,状态由第一个完成的promise决定

*/

Promise.race = function(value){

}

2. 实现Promise构造函数


  1. 众所周知,构造函数里由resolve和reject方法,而且这两个方法会被传入executor,并且executor立即同步执行

/*

Promise构造函数

executor:执行器函数

*/

function Promise(executor) {

function resovle() {

}

function reject() {

}

// 立即同步执行executor

executor(resovle,reject)

}

  1. 家喻户晓的是,每个promise都有一个状态可能为pending或resolved,rejected。因此需要添加个status,此外,当我们这样使用Promise的时候,

// 例1

var promise = new Promise((resovle,reject)=>{

})

promise.then(resolve=>{},reject=>{})

这时执行到then,promise的状态还是pending,这时要把值和then里面的回调函数保存起来,所以需要个data和callbacks

function Promise(executor) {

var self = self

self.status = ‘pending’ // 给promise对象指定status属性,初始值为pending

self.data = undefined // 给promise对象指定一个存储结果的data

self.callbacks = [] // 每个元素的结构:{onResolved(){},onRejected(){}}

function resovle() {

}

function reject() {

}

// 立即同步执行executor

executor(resovle,reject)

}

  1. 妇孺皆知的是,在上面的例子1的基础上,当我们执行resovle(value)时,

// 例2

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

setTimeout(function () {

resolve(1)

})

})

promise.then(resolve=>{},reject=>{})

会把promise对象的status改为resovle,并且把value保存到data,然后执行之前保存的callbacks(上面说过当执行到then时,发现当前的promise是pending状态,会把then里的回调函数保存到promise的callbacks里)。

function resolve(value) {

// 如果当前状态不是pending,则不执行

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

return

}

// 将状态改为resolved

self.status = ‘resolved’

// 保存value的值

self.data = value

// 如果有待执行的callback函数,立即异步执行回调函数onResolved

if (self.callbacks.length>0){

setTimeout(()=>{

self.callbacks.forEach(callbackObj=>{

callbackObj.onResolved(value)

})

})

}

}

  1. 我们还知道,promise的状态只能改变一次,因此当执行resolve的时候要判断是不是promise是不是pending的状态,否则是不能执行的

function resolve(value) {

// 如果当前状态不是pending,则不执行

if(this.status !== ‘pending’){

return

}

// 将状态改为resolved

this.status = ‘resolved’

// 保存value的值

this.data = value

// 如果有待执行的callback函数,立即异步执行回调函数onResolved

if (this.callbacks.length>0){

setTimeout(()=>{

this.callbacks.forEach(callbackObj=>{

callbackObj.onResolved(value)

})

})

}

}

  1. 异曲同工之妙的是reject方法也是这个道理,因此这里无需赘述

function reject(value) {

// 如果当前状态不是pending,则不执行

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

return

}

// 将状态改为resolved

self.status = ‘rejected’

// 保存value的值

self.data = value

// 如果有待执行的callback函数,立即异步执行回调函数onResolved

if (self.callbacks.length>0){

setTimeout(()=>{

self.callbacks.forEach(callbackObj=>{

callbackObj.onRejected(value)

})

})

}

}

  1. 我们又知道,当在执行executor的时候,如果执行异常的话,这个promise的状态会直接执行reject方法。

// 例 3

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

执行到这里出错了

setTimeout(function () {

resolve(1)

})

})

要实现这个功能,我们可以在executor外让try catch来捕获

try{

// 立即同步执行executor

executor(resolve,reject)

}catch (e) { // 如果执行器抛出异常,promise对象变为rejected状态

reject(e)

}

好了,现在来测试一下,为了测试,我们需要简单的实现下then,让它往callbacks里push then里的回调函数

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

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

this.callbacks.push({

onResolved,

onRejected

})

}

好了,现在测试下,发现成功。

// 例4

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

setTimeout(function () {

// resolve(1)

reject(1)

},100)

})

promise.then(

value=>{

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状态

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

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

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

img

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

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

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

核心竞争力,怎么才能提高呢?

成年人想要改变生活,逆转状态?那就开始学习吧~

万事开头难,但是程序员这一条路坚持几年后发展空间还是非常大的,一切重在坚持。

为了帮助大家更好更高效的准备面试,特别整理了《前端工程师面试手册》电子稿文件。

前端面试题汇总

JavaScript

性能

linux

前端资料汇总

完整版PDF资料免费分享,只需你点赞支持,动动手指点击此处就可免费领取了

前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。

(img-dQoUiwX1-1712258825668)]

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

[外链图片转存中…(img-1XFTholb-1712258825669)]

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

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

核心竞争力,怎么才能提高呢?

成年人想要改变生活,逆转状态?那就开始学习吧~

万事开头难,但是程序员这一条路坚持几年后发展空间还是非常大的,一切重在坚持。

为了帮助大家更好更高效的准备面试,特别整理了《前端工程师面试手册》电子稿文件。

前端面试题汇总

JavaScript

性能

linux

前端资料汇总

完整版PDF资料免费分享,只需你点赞支持,动动手指点击此处就可免费领取了

前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。

  • 27
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值