ES6 Promise

17 篇文章 0 订阅
15 篇文章 0 订阅

一,Promise到底是个啥?

promise是一个构造函数,它用来封装异步操作,可以有效解决回调地狱问题

以下使用promise封装ajax请求


    var btn = document.getElementById('btn')
    btn.onclick = function () {
        const p = new Promise((resolve, reject) => {
            // 创建对象
            const xhr = new XMLHttpRequest
            // 初始化
            xhr.open('GET', 'https://xxxxx')
            // 发送
            xhr.send()
            // 处理相应结果
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        resolve(xhr.response)
                    } else {
                        reject(xhr.status)
                    }
                }

            }
        })
        p.then(value => {
            console.log(value);
        }, reason => {
            console.log(reason);
        })

    }

二, Promise有三个状态:pendding,resolved,rejeced,那么如何改变promise的状态呢?

1,执行resolve()会将状态变为resolved
2,执行reject()会将状态变为rejected
3,抛出错误 thow会将状态变为rejected

三,如果使用then方法指定多个成功、失败的回调,这些回调都会执行吗?

都会执行!!!

四,改变promise状态和<指定>回调函数谁先谁后?

这取决于resolve()/reject()和then()在那调用,这涉及到js事件循环的知识

五,then方法返回的结果由什么决定?

由then方法指定的回调函数的执行结果决定的
在这里插入图片描述

六,promise异常穿透

在使用promise的then的链式调用的时候,可以在最后指定失败的回调,前面任何操作的异常,都会传到最后失败的回调中处理
在这里插入图片描述

七,怎么中断promise链条?

在链式调用中返回一个pending状态的promise对象即可
在这里插入图片描述

八,手写Promise

  // Promise是一个构造函数,可以封装异步的任务,并且对结果进行处理
    // promise支持链式调用,可以用来解决回调地狱的问题,在指定回调和错误处理方面更加灵活
    function my_Promise(executor) {
        this.promiseStatus = 'pending'
        this.promiseResult = null
        // 如果给一个promise对象指定多个回调函数,当状态改变时,这些回调都会生效
        this.callbacks = []
        // 因为执行resolve/reject的时候函数的this指向window而不是实例对象,所以需要保存这里的this
        const self = this
        function resolve(data) {
            if (self.promiseStatus !== 'pending') return
            self.promiseStatus = 'resolved'
            self.promiseResult = data
            self.callbacks.forEach(item => {
                item.onResolved(data)
            });

        }
        function reject(data) {
            if (self.promiseStatus !== 'pending') return
            self.promiseStatus = 'rejected'
            self.promiseResult = data
            self.callbacks.forEach(item => {
                item.onReject(data)
            });

        }
        try {
            executor(resolve, reject)
        } catch (error) {
            reject(error)
        }

    }

    my_Promise.prototype.then = function (onResolved, onReject) {
        if (this.promiseStatus === 'resolved') onResolved(this.promiseResult)
        if (this.promiseStatus === 'rejected') onReject(this.promiseResult)
        if (this.promiseStatus === 'pending')
            this.callbacks.push({ onResolved, onReject })
    }

    // 测试
    // var p = new my_Promise((resolve, reject) => {
    //     setTimeout(() => {
    //         resolve('okkkkkk')
    //     }, 2000);
    // })

    // p.then(value => {
    //     console.log(value);
    // }, reason => {
    //     console.warn(reason);
    // })
    // p.then(value => {
    //     alert(value);
    // }, reason => {
    //     console.warn(reason);
    // })



    // Promise.all方法:可以将多个Promise实例包装成一个新的Promise实例。
    // 同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。
    my_Promise.all = function (promises) {
        return new my_Promise((resolve, reject) => {
            var arr = []
            promises.forEach((item, index) => {
                item.then(value => {
                    arr[index] = value
                    if (arr.length === promises.length) {
                        resolve(arr)
                    }
                }, reason => {
                    reject(reason)
                })
            })
        })
    }
    // // 测试
    // var p1 = new my_Promise((resolve, reject) => {
    //     resolve('okk')
    // })
    // var p2 = new my_Promise((resolve, reject) => {
    //     resolve('hello')
    // })
    // var p3 = new my_Promise((resolve, reject) => {
    //     reject('kang')
    // })
    // var pros = [p1, p2, p3]

    // console.log(my_Promise.all(pros));


    // Promise.race方法:Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])
    // 里面哪个结果获得的快,就返回那个结果
    my_Promise.race = function (promises) {
        return new Promise((resolve, reject) => {
            for (var i = 0; i < promises.length; i++) {
                promises[i].then(value => {
                    resolve(value)
                }, reason => {
                    reject(reason)
                })
            }
        })
    }

    // let p1 = new Promise((resolve, reject) => {
    //     setTimeout(() => {
    //         resolve('success')
    //     }, 1000)
    // })

    // let p2 = new Promise((resolve, reject) => {
    //     setTimeout(() => {
    //         reject('failed')
    //     }, 5000)
    // })
    // // 测试
    // my_Promise.race([p1, p2]).then((result) => {
    //     console.log(result)
    // }).catch((error) => {
    //     console.log(error)  // 打开的是 'failed'
    // })

Promise.all()

接收一个由promise组成的数组(如果数组里不是promise,那么会调用Promise.resolve()将其转化为Promise),返回的结果是一个Promise,状态由传进来的这些promise状态决定,

  • 他们的状态全是fullfilled那Promise.all返回的promise状态就是就是fulfilled,值是传进来的promise数组返回的值,顺序跟传进来的顺序一致。
  • 只要有一个是failed,那么Promise.all()返回的promise的状态就是failed,值就是第一个失败了的promise的值

Promise.race()

接受由多个promise实例构成的数组(如果数组里不是promise,那么会调用Promise.resolve()将其转化为Promise)返回的结果也是一个promise实例,跟传进来的promise实例中第一个改变状态的Promise保持一致。

async await

async/await是Generator和yield的语法糖
async相当于Generator,await相当于yield
Generator方式的函数里面代码会分段执行,看到yield就分一段
使用async/await比较方便,代码清晰
async/await也是解决异步的一个办法,背后原理就是Generator和yield,当一个函数前面加上了async,这个函数就变成了异步的函数
await必须要在async修饰的函数内部使用,他会阻塞后面的代码,等到主线程的任务执行完了之后才会回来执行
在这里插入图片描述
async,await 代码输出:

async function async1() {
  console.log("async1 start");
  await async2();
  console.log("async1 end");
}
async function async2() {
  console.log("async2");
}
async1();
console.log('start')

答案:
‘async1 start’
‘async2’
‘start’
‘async1 end’
过程分析:

首先一进来是创建了两个函数的,我们先不看函数的创建位置,而是看它的调用位置
发现async1函数被调用了,然后去看看调用的内容
执行函数中的同步代码async1 start,之后碰到了await,它会阻塞async1后面代码的执行,因此会先去执行async2中的同步代码async2,然后跳出async1
跳出async1函数后,执行同步代码start
在一轮宏任务全部执行完之后,再来执行刚刚await后面的内容async1 end。

在这里,你可以理解为紧跟着await后面的语句相当于放到了new Promise中,下一行及之后的语句相当于放在Promise.then中

async function async1 () {
  console.log('async1 start');
  await new Promise(resolve => {
    console.log('promise1')
  })
  console.log('async1 success');
  return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')

  • 在async1中await后面的Promise是没有返回值的,也就是它的状态始终是pending状态,因此相当于一直在await,await,await却始终没有响应…
  • async函数中抛出了错误或者reject(),则终止错误结果,不会继续向下执行。可以用try catch捕获
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值