IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 手动实现Promise方法(原理) -> 正文阅读

[JavaScript知识库]手动实现Promise方法(原理)

我们在使用Promise,为了解决异步操作,去实现同步代码的作用

平时开发时候,我们很多时候,需要等待接口返回后,去做一些处理,或者借用返回值,再调用,,如果用传统的方法,我们容易陷入回调地狱的问题,代码的可读性也不是很好

现在我们来看下Promise的原理,是如何实现的

1、Promise是一个类,执行这个类的时候,需要传入一个执行器进去,执行器立即执行

class myPromise{
    // executor执行器
    constructor(executor){
        executor(this.resolve,this.reject)
    }
    resolve(){}
    reject(){}
}

2、Promsise有三种状态,分别为padding、fulfilled、rejected,当状态变为fulfilled或者rejected后,状态就不可以再改变

3、resolve和reject函数是用来更改状态的 resolve = fulfilled reject = rejected

let result = new Promise((resolve,reject)=>{
    resolve('成功')
    reject('失败')
})
result.then((res)=>{
    console.log(res) // 成功,状态变成了fulfilled
},(err)=>{
    console.log(err) // 不会执行
})

现在我们来实现下resolve和reject是怎么改变状态的

const PADDING = 'padding' // 等待
const FULFILLED = 'fulfilled' // 成功
const REJECTED = 'rejected' // 失败
// 成功的返回值
let value = null
// 失败的返回值
let reason = null

class myPromise {
	// executor执行器
	constructor(executor) {
		executor(this.resolve, this.reject)
	}
	status = PADDING
	resolve=(val)=> {
	    // 状态改变了之后,,就不能再改变
	    if (this.status !== PADDING) return
		this.status = FULFILLED
	    value = val
	}
	reject=(err)=> {
	    // 状态改变了之后,,就不能再改变
		if (this.status !== PADDING) return
		this.status = REJECTED
	    reason = err
	}

	// 这里还有一个then方法
	then=(successCallback, failCallback)=> {
        // 状态是成功,我们就执行成功的回调
	    if (this.status === FULFILLED) {
			successCallback(value)
		}
        // 状态是失败,我们就执行失败的回调
		if (this.status === REJECTED) {
		    failCallback(value)
		}
	}
}

现在我们来执行下myPromise

new myPromise((resolve,reject)=>{
    resolve('success')
    reject('error')
}).then(res=>{
    console.log(res) // success
},err=>{
    console.log(err) // 不会执行
})

结果是出来了,但是如果我们的promise里面是异步怎么办呢,执行结果还是这个么,我们用setTimeout来模拟下

new myPromise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('success')
    },1000) 
}).then(res=>{
    console.log(res) // null
},err=>{
    console.log(err) // 不会执行
})

在then里面并不会返回我们想要的成功success,是什么原因呢,我们来想一下

1、then里面的回调函数,要在resolve或者reject执行完以后,去调用回调,这样是不是就可以拿到我们想要的结果,

2、我们可以把then的回调函数保存起来,在执行resolve或者reject时候,再把回调函数拿出来执行

3、我们是把回调放在一个数组中,在resolve或者reject里面,从数组中拿出来执行

const PADDING = 'padding' // 等待
const FULFILLED = 'fulfilled' // 成功
const REJECTED = 'rejected' // 失败
// 成功的返回值
let value = null
// 失败的返回值
let reason = null

class myPromise {
	// executor执行器
	constructor(executor) {
		executor(this.resolve, this.reject)
	}
    // 开始状态-等待
	status = PADDING
    // 保存成功的回调函数
    successCallbackList = []
    // 保存失败的回调函数
    failCallbackList = []

	resolve=(val)=> {
	    // 状态改变了之后,,就不能再改变
	    if (this.status !== PADDING) return
		this.status = FULFILLED
	    value = val
        while(this.successCallbackList.length){
            this.successCallbackList.shift()()
        }
	}
	reject=(err)=> {
	    // 状态改变了之后,,就不能再改变
		if (this.status !== PADDING) return
		this.status = REJECTED
	    reason = err
        while(this.failCallbackList.length){
            this.failCallbackList.shift()()
        }
	}

	// 这里还有一个then方法
	then=(successCallback, failCallback)=> {
        // 状态是成功,我们就执行成功的回调
	    if (this.status === FULFILLED) {
			successCallback(value)
		}else if(this.status === REJECTED){
            failCallback(value)
        }else{
            // 状态在等待的,我们添加到数组中
            this.successCallbackList.push(successCallback)
            this.failCallbackList.push(failCallback)
        }
	}
}

现在我们来看异步的情况下,执行结果

new myPromise((resolve,reject)=>{
    setTimeout(()=>{
        resolve('success')
    },1000) 
}).then(res=>{
    console.log(res) // success 1秒之后,控制台打印‘success’
})

实现了异步的情况

都知道promise是链式调用,我们可以在后面加很多个then,第一个then的值是我们promise,resolve出来的值,那我们第二个then呢,值是哪里来的?我们可以尝试下Promise,看看执行then,是什么

?返回的是一个Promise,那么我们就可以直接链接then方法

let result = new Promise((resolve)=>{
    resolve()
}).then(()=>{
    return '你好'
})
result.then(res=>{
    console.log(res) // 你好
})

所有我们知道了,Promise的then方法,里面的返回值是一个Promise

下面我们就来实现它


then=(successCallback, failCallback)=>{
    let promise = new myPromise((resolve,reject)=>{
         // 状态是成功,我们就执行成功的回调
	    if (this.status === FULFILLED) {
			let result = successCallback(value)
            if(result instanceof myPromise){
                result.then(resolve,reject)
            }else{
                resolve(result)
            }
		}else if(this.status === REJECTED){
            let errResult = failCallback(value)
            if(errResult instanceof myPromise){
                errResult.then(resolve,reject)
            }else{
                resolve(errResult)
            }
        }else{
            // 状态在等待的,我们添加到数组中
            this.successCallbackList.push(successCallback)
            this.failCallbackList.push(failCallback)
        }
    })

    return promise
}

这样就实现了promise的链式调用

Promise的all方法

1、all

static all=(array)=>{
    // 结果储存在result中
    let result = []
    let index = 0
    return new Promise((resolve,reject)=>{
        function addData (i,value){
            result[i] = value
            // 执行成功一项,记录下来,当所有都执行成功后,resolve出所有的值
            index++   
            if(index===array.length){
                resolve(result)
            }
        }
        for(let i; i<array.length; i++){
            let current = array[i]
            // 如果是promise,把then的结果放入result中
            if(current instanceof myPromise){
                current.then(res=>addData(i,res),err=>reject(err))
            }else{
                // 不是promise,直接放入result
                addData(i,current)
            }
        }
    })
}

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-24 09:20:29  更:2022-04-24 09:21:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:55:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码