Promise从入门到自定义之手写Promise(前端进阶必学)

promise前端进阶

一、准备工作

1、区别实例对象跟函数对象

  • 函数对象:将函数作为对象使用时
  • 实例对象:new 函数生产的对象

function Fn(){} //Fn函数

const fn = new Fn() //Fn是构造函数 fn是实例对象

Fn.prototype //Fn是函数对象

Fn.call({}) //Fn是函数对象

$('#test') //jQuery函数

$.get('/') //jQuery函数对象

总结:点的左边是对象,括号的左边是函数

2、回调函数的分类

同步回调

立即执行,完全执行完了才结束,不会放入回调队列

例子:数组遍历相关的回调函数、promise的excutor函数

// 同步回调
const arr=[1,2,3]
arr.forEach(item =>{
	console.log(item)
})
console.log('forEach后')
/*
运行结果:
1 
2 
3 
forEach后
*/
异步回调

不立即执行,会放入回调队列中将来执行

例子:定时器回调、ajax回调、promise的成功失败

// 异步回调
setTimeout(arr=>{
	console.log('arr')
},0)
console.log('setTimeout之后')
/*
运行结果:
setTimeout之后 
arr
*/

3、error错误处理

错误的类型

  • Error:所有错误的父类型
  • ReferenceError:引用的变量不存在
  • TypeError:数据类型不正确的错误
  • SyntaxError:语法语法

捕获错误:try...catch

抛出错误:throw error

错误对象

  • message属性:错误相关信息
  • stack属性:函数调用栈记录信息

二、promise的理解与使用

1、promise是什么

理解
  • 抽象表达:

    promise是js中异步编程的新的解决方案

  • 具体表达:

    1. promise是一个构造函数
    2. promise对象用来封装一个异步操作并可以获取其结果
promise的状态改变
  1. pending变为resolved

  2. pending变为rejected

    只有这2种,且一个promise对象只能改变一次无论失败还是成功

    成功一般称为value,失败称为reason

工作原理图

使用流程实例
<script>
        // 1.创建一个新的promise对象
        const p = new Promise((resolve,reject)=>{
        // 2.执行异步操作任务
            const time = Date.now()//偶数成功,奇数失败
        // 3.1如果成功,调用resolve(value)
            if(time %2 == 0){
                resolve('成功的数据,time='+time)
            }else {
            // 3.2如果失败,调用reject(reason)
                reject('失败的数据,time='+time)
            }
        
        })
        p.then(
            value => {//接受到的成功value数据
                console.log('成功的个回调',value)
            },
            reason =>{//接受到失败的reason数据
                console.log('失败的回调',reason)
            }
        )
    </script>

2、为什么用promise

指定回调函数的方式更加灵活

因为没用Promise之前,使用回调函数时,传入的回调函数必须放在前面,放到后边就用不到了,导致得不到数据

  • 旧的:说白了原来的方式就是必须在启动异步任务前指定

  • promise:启动异步任务=》返回promise对象=》给promise对象绑定回调函数(甚至可以在异步)

支持链式调用,可以解决回调地狱

回调地狱

回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调函数执行的条件

doSomething(function (result) {
     doSomethingElse(result, function (newResult) {
         doThirdThing(newResult, function (finalResult) {
             console.log('Got the final result: ' + finalResult)
         }, failureCallback)
     },failureCallback)
 }, failureCallback)

promise解决回调地狱

一个promise对应一个异步结果

doSomething()
.then( function( result) {
return doSomethingElse(result)
})
.then( function(newResult) {
return doThirdThing( newResult)
})
.then( function(finalResult) {
console.log('Got the final result: ' + finalResult)
})
.catch( failureCallback) 

async / await: 回调地狱的终极解决方案

async function request() {
    try {
        const result = await doSomething()
        const newResult = await doSomethingElse(result)
        const finalResult = await doThirdThing(newResult)
        console.log('Got the final result: ' + finalResult)
    } catch (error) {
        failureCallback(error)
    }
}

3、如何使用promise

API
  1. Promise构造函数:

    Promise (excutor) {}

  • excutor函数:同步执行(resolve, reject) => {}

  • resolve函数:内部定义成功时我们调用的函数value => { }

  • reject函数:内部定义失败时我们调用的函数reason => {}

    说明: excutor 会在Promise内部立即同步回调,异步操作在执行器中执行

  1. Promise.prototype.then方法: ``(onResolved, onRejected) => {}
  • onResolved函数:成功的回调函数(value) => {}

  • onRejected函数:失败的回调函数(reason) => {}

    说明:指定用于得到成功value的成功回调和用于得到失败reason的失败回调
    返回一个新的promise对象

  1. Promise.prototype.catch方法:(onRejected) => {}`
  • onRejected函数:失败的回调函数(reason) => {}

    说明: then()的语法糖, 相当于: then(undefined, onRejected )

  1. Promise.resolve方法: (value) => {}
  • value:成功的数据或promise对象

    说明:返回一个成功/失败的promise对象

  1. Promise.reject方法: (reason) => {}

    • reason:失败的原因

      说明:返回一个失败的promise对象

  2. Promise.al1方法: (promises) => {}

  • promises:包含n个promise的数组

    说明:返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败了就直接失败

  1. Promise.race方法: (promises) => {}
  • promises :
    包含n个promise的数组

    说明:返回一个新的promise,第-” 个完成的promise的结果状态就是最终的结果状态

4、promise的关键问题

如何改变promise 的状态
  • resolve:如果当前是pendding就会变为resolved
  • reject:如果当前是pendding就会变为rejected
  • 抛出异常:如果当前是pendding就会变为rejected
当一个promise指定多个成功、失败回调函数,都会调用吗

当promise改变状态时就会调用

promise.then()返回的新promise的结果状态由什么决定

由then指定的回调函数执行的结果决定

三、手写promise

第一步:搭建框架

  1. 创建一个手写promise.js的js文件来实现promise

  2. 将这个文件引入一个自定义promise.html的文件中去使用

/*
自定义Promise模块
*/
(function (window) {
    /*
    promise 构造函数
    executor :执行器函数(同步执行函数)
    */ 
    function Promise(executor) {
        
    } 

    /*
    Promise原型对象的then()
    指定成功失败的回调函数
        返回一个新的promise对象
    */
    Promise.prototype.then = function (onResolved,onRejected) {
        
    }

    /*
    Promise原型对象的catch()
    指定失败的回调函数
        返回一个新的promise对象
    */
    Promise.prototype.catch = function (onRejected) {

    }

    /*
    Promise函数对象resolve方法
    返回指定结果的一个成功的promise
    */
    Promise.resolve = function (value) {
        
    }

    /*
        Promise函数对象reject方法
        返回一个指定reason的失败的promise
    */
    Promise.reject = function (reason) {

    }

    /*
        Promise函数对象all方法
        返回一个promise,只有当所有promise都成功时才成功,否则失败
            (只要有一个失败,就失败)
    */
    Promise.all = function (promises) {

    }


    /*
        Promise函数对象race方法
        返回一个promise,结果由第一个完成的promise来决定
    */
    Promise.race = function (promises) {

    }


    // 向外暴露promise函数
    window.Promise = Promise
})(window)

第二步:搭建executor执行器函数

自定义promise.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义promise</title>
</head>
<body>
    <script src="手写promise.js"></script>
    <script>
        new Promise((resolve,reject)=>{
            resolve(1) //value
            reject(2) //reason
        })
    </script>
</body>
</html>

自定义promise.js

将执行器函数简单封装下

function Promise(executor) {

        this.status = 'pending' //给promise对象指定status属性,初始值为pending
        this.data = undefined //给promise对象指定一个用于存储结果数据的属性
        this.callbacks = [] //每个元素的结果:{onResolved(){},onRejected(){}}


        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(callbacksObj => {
                        callbacksObj.onResolved(value)
                    })
                })
            }
        }

        function reject(reason) {
            //如果当前状态不是pending,直接结束
            if (this.status !== 'pending') {
                return
            }

            //将状态改为rejected
            this.status = 'rejected'
            //保存value数据
            this.data = reason
            //如果有待执行callback函数,立即异步执行回调函数onRejected
            if (this.callbacks.length > 0) {
                setTimeout(() => {//放入队列中执行所有成功的回调
                    this.callbacks.forEach(callbacksObj => {
                        callbacksObj.onRejected(reason)
                    })
                })
            }
        }
        // 立即同步执行executor
        try {
            executor(resolve, reject)
        } catch (error) {//如果执行器抛出异常,promise对象变为rejected状态
            reject(error)
        }
    }

第三步:优化executor执行器跟简单实现then()方法

function Promise(executor) {

        // 将当前promise对象保存起来
        const self = this
        self.status = 'pending' //给promise对象指定status属性,初始值为pending
        self.data = undefined //给promise对象指定一个用于存储结果数据的属性
        self.callbacks = [] //每个元素的结果:{onResolved(){},onRejected(){}}


        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(callbacksObj => {
                        callbacksObj.onResolved(value)
                    })
                })
            }
        }

        function reject(reason) {
            //如果当前状态不是pending,直接结束
            if (self.status !== 'pending') {
                return
            }

            //将状态改为rejected
            self.status = 'rejected'
            //保存value数据
            self.data = reason
            //如果有待执行callback函数,立即异步执行回调函数onRejected
            if (self.callbacks.length > 0) {
                setTimeout(() => {//放入队列中执行所有成功的回调
                    self.callbacks.forEach(callbacksObj => {
                        callbacksObj.onRejected(reason)
                    })
                })
            }
        }
        // 立即同步执行executor
        try {
            executor(resolve, reject)
        } catch (error) {//如果执行器抛出异常,promise对象变为rejected状态
            reject(error)
        }
    }

    /*
    Promise原型对象的then()
    指定成功失败的回调函数
        返回一个新的promise对象
    */
    Promise.prototype.then = function (onResolved, onRejected) {
        const self = this

        //假设当前状态还是pending状态,将回调函数保存起来
        self.callbacks.push({
            onResolved,
            onRejected
        })
    }

第四步:简单构建then()方法

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

        if (self.status === PENDING) {
            //假设当前状态还是pending状态,将回调函数保存起来
            self.callbacks.push({
                onResolved,
                onRejected
            })
        } else if (self.status === RESOLVED) {
            setTimeout(() => {
                /*
                1、如果抛出异常,return promise就会失败,reason就是error
                2、如果回调函数执行返回非promise,return的promise成功,value就是返回的值
                3、如果回调函数返回的是promise,return的promise结果就是这个promise的结果
                */
                try {
                    const result = onResolved(self.data)
                    // 3、如果回调函数返回的是promise,return的promise结果就是这个promise的结果

                    if (result instanceof Promise) {
                        result.then(
                            value => resolve(value),//当result成功,让return的promise也成功
                            reason => reject(reason)//当result失败,让return的promise也失败
                        )
                    } else {
                        //2、如果回调函数执行返回非promise,return的promise成功,value就是返回的值
                        resolve(result)
                    }

                } catch (error) {
                    // 1、如果抛出异常,return promise就会失败,reason就是error
                    reject(error)
                }
            });
        } else { //'rejected'
            setTimeout(() => {
                onRejected(self.data)
            });

        }

        // 返回一个新的promise对象
        return new Promise((resolve,reject) => {
            
        })
    }
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值