美文网首页
Part1.模块一:函数式编程与 JS 异步编程、手写 Prom

Part1.模块一:函数式编程与 JS 异步编程、手写 Prom

作者: 油菜又矮吹 | 来源:发表于2020-07-20 23:39 被阅读0次

    简答题

    一、谈谈你是如何理解JS异步编程的,EcentLoop、消息队列都是做什么的,什么是宏任务,什么是微任务?

    • JS 异步编程:
      • 解答:
               JavaScript语言的执行环境是单线程,单线程是指一次只能完成一个任务,如果有多个任务,则需要排队,等待前一个任务完成后,才能开始后一个任务。基于这种原因而产生了两种执行任务的模式:同步模式和异步模式,且随着JavaScript面临的需求要来越多,它可以运行在浏览器、服务器上等,为了满足这些需求,使得JavaScript的规模和复杂性也在持续增长,所以JavaScriptd中的异步编程也在不断地调整,往更友好的方向发展,JavaScript异步编程经历了回调函数、Promise、生成器函数Generator、以及现在Async/Await等几个发展阶段。
               在第一阶段使用的是回调函数,它是最基本的异步操作方式,以Ajax请求最为常见,它是最简单、容易理解和实现的异步编程;但是不利于代码的阅读和维护,各部分之间高度耦合,使得程序结构混乱,流程难以追踪,每个任务只能指定一个回调函数,不能使用try catch捕获错误,不能直接return,且极易出现回调地狱导致的调式困难,以及控制反转导致的一系列信任问题
    ajax(urlA, () => {
        // 处理逻辑
        ajax(urlB, () => {
            // 处理逻辑
            ajax(urlC, () => {
                // 处理逻辑
            })
        })
    })
    

           在第二阶段引入了Promise,它是ES6推出的一种异步编程的解决方案。Promise是承诺的意思,这个承诺在未来某个时刻会有一个确定的答复,该承诺有三种状态:等待中(pending)、完成(resolved)、拒绝(rejected)。Promise是个构造函数,接受一个函数作为参数。作为参数的函数有两个参数:resolve和reject,分别对应完成和拒绝两种状态。我们可以选择在不同时候执行resolve或reject去触发下一个动作,执行then方法里的函数。Promise实现了链式调用,每次调用then之后返回的都是一个Promise对象,如果在then使用了return,return返回的值会被Promise.resolve()包装。它很好的解决了回调函数中的回调地狱,解决了控制反转导致的信任问题,将代码的执行主动权拿了回来;但是Promise一旦状态从等待改变为其他状态就不再可变了,还有如果不设置回调函数,Promise内部抛出的错误。

    new Promise((resolve, reject) => {   
        console.log('new Promise');   
        resolve('success'); }) 
        console.log('end');
    

           第三阶段使用生成器函数Generator,它是一种特殊的函数,其最大的特点是控制函数的执行。可以让我们用同步的方式写代码,可以分步执行并得到异步操作的结果,能够知晓异步操作的过程,以及切入修改异步操作的过程。但是需要手动去控制next(...),将回调成功的返回数据送回JavaScript的主流程中;

    function *foo(x) {
      let y = 2 * (yield (x + 1));
      let z = yield (y / 3);
      return (x + y + z);
    }
    let it = foo(5);
    console.log(it.next());   // => {value: 6, done: false}
    console.log(it.next(12)); // => {value: 8, done: false}
    console.log(it.next(13));// => {value: 42, done: true}
    

           最新阶段的Async/Await异步处理编程,其中async函数返回一个 Promise 对象,就是将函数返回使用Promise.resolve(),和then处理返回值一样,可以使用then方法添加回调函数。await后边一般跟Promise对象,async函数执行遇到await后,等待后面的Promise对象的状态从pending变成resolve后,将resolve的参数返回并自动往下执行直到下一个await或结束。它解决了Generator需要手动控制next(...)执行的问题。但它存在一个缺陷是如果多个异步代码没有依赖性却使用了await会导致性能降低。

    async function test() {
        console.log('1')
    }
    console.log(test)   // Promise {<resolve>: "1"}
    

           整个异步过程都是通过内部的消息队列和事件循环实现的
           每个阶段的突破都是为了解决现有阶段的技术问题,异步编程的发展也是一个循序渐进的过程。

    • EventLoop、消息队列:
      • 解答:
               事件循环机制和消息队列的维护是由事件触发线程控制的,事件触发线程是由浏览器渲染引擎提供的,它会维护一个消息队列
               EventLoop是事件循环,主要负责监听调用栈(执行栈)和消息队列(任务队列),一旦调用栈中所有的任务都结束了,事件循环就会从消息队列中取出第一个回调函数,然后压入到调用栈中,一旦消息队列中发生了变化,事件循环就会监听到
               消息队列:消息队列是类似队列的数据结构,遵循先入先出(FIFO)的规则。如果把调用栈理解为正在执行的工作表,那么消息队列则可以理解成待办的工作表,JS引擎会先做完调用栈中所有的任务,然后通过事件循环从消息队列中再取一个任务出来继续执行,以此类推,整个过程随时可以往消息队列中再去放任务,这些任务在消息队列中会排队等待事件循环
               事件循环机制:
                   1.JS引擎线程会维护一个执行栈,同步代码会依次加入执行栈中,然后依次执行并出栈
                   2.JS引擎线程遇到异步函数,会将异步函数交给相应的WebApi,并继续执行后面的任务
                   3.WebApi会在条件满足的时候,将异步对应的回调加入到消息队列中,等待执行
                   4.执行栈为空时,JS引擎线程会去取消息队列中的回调函数(如果有的话),并加入到执行栈中执行
                   5.完成后出栈,继续执行4的操作,直至消息队列中的回调函数为空,以上便是事件循环的机制
    • 宏任务、微任务
      • 解答:
               在JS中,有两类任务队列:宏任务队列(macrotask)和微任务队列(microtask),宏任务可以由多个,微任务只有一个
        • macrotask:主代码块、setTimeout、setInterval、setImmediate、I/O、UI rendering等(可以看到,事件队列中的每一个事件都是一个 macrotask,现在称之为宏任务队列)
        • microtask:Promise、process.nextTick、Object.observer等

           每次执行栈执行的代码即是一个宏任务,包括任务队列(宏任务队列)中的,因为执行栈中的宏任务执行完后会去取任务队列(宏任务队列)中的任务加入执行栈中
           在执行宏任务时遇到Promise等,会创建微任务(.then()里面的回调),并加入到微任务队列队尾;微任务必然是在某个宏任务执行的时候创建的,而在下一个宏任务开始之前,浏览器会对页面重新渲染。同时,在上一个宏任务执行完成后,渲染页面之前,会执行当前微任务队列中的所有微任务。
           执行机制
               1.执行一个宏任务(执行栈中没有就从消息队列中获取)
               2.执行过程中如果遇到微任务,就将微任务添加刀微任务的任务队列中
               3.宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
               4.当前宏任务执行完毕,开始检查渲染,然后GUI接管渲染
               5.喧渲染完毕后,JS引擎线程继续,开始下一个宏任务(从宏任务队列中获取)

    代码题

    一、将下面异步代码使用Promise的方式改进

    异步代码.png
    解答:使用Promise的方式改进实现如下:
    // 使用Promise改进setTimeout异步代码
    new Promise((resolve, reject) => {
        resolve('hello')
    }).then(value => {
        return value + ' ' + 'lagou' // value = hello 
    })
    .then(value => {
        return value + ' ' + 'I ♥ U'  // value = hello lagou 
    })
    .then(value => {
        console.log(value)   // hello lagou I ♥ U
    })
    

    二、基于以下代码完成四个练习

    代码1-题目.png
    代码2-题目.png
    练习1:使用组合函数fp.flowRight()重新实现下面这个函数
    练习1-题目.png
    解答:fp.flowRight()重新实现如下:
    //练习1
    let isLastInstock = fp.flowRight(fp.prop('in_stock') , fp.last)
    console.log(isLastInstock(cars)) //false   即最后一条数据的in_stock属性值为fase
    
    练习2:使用fp.flowRight(),fp.prop(),fp.first()获取第一个car的name

    解答:获取第一个car的name实现如下:

    // 练习2
    let getFirstCarName = fp.flowRight(fp.props('name'), fp.first)
    console.log(getFirstCarName(cars))  //[ 'Ferrari FF' ]
    
    练习3:使用帮助函数_average()重构averageDollarValue,使用函数组合方式实现
    练习3-题目.png
    解答:重构averageDollarValue实现如下:
    let averageDollarValue = fp.flowRight(_average,fp.map(car => car.dollar_value))
    console.log(averageDollarValue(cars))  //790700
    
    练习4:使用flowRight写一个sanitizeName()函数,返回一个下划线连接的小写字符串,把数组中的name转换为这种形式,例如:sanitizeName(["Hello World"]) => ["hello_world"]
    练习4-题目.png
    解答:使用flowRight写一个sanitizeName()函数实现如下:
    // 练习4
    let _underscore = fp.replace(/\W+/g, '_')
    
    //先遍历数组把里面字符串转成小写,在遍历数组将非单字字符转换成下划线
    let sanitizeName1 = fp.flowRight( fp.map(_underscore), fp.map(fp.toLower))
    //遍历数组中使用fp.flowRight组合函数,先转换成小写,再将非单字字符转换成下划线
    let sanitizeName2 = fp.flowRight( fp.map(fp.flowRight(_underscore, fp.toLower)))
    console.log(sanitizeName2(["Hello World",'LaGou Study']))  //[ 'hello_world', 'lagou_study' ]
    

    三、基于下面提供的四个代码,完成后续的四个练习

    代码1-题目.png
    代码2-题目.png
    代码3-题目.png
    练习1:使用fp.add(x,y)和fp.map(f,x)创建一个能让functor里的值增加的函数ex1
    练习1-题目.png
    解答:让functor里的值增加的函数实现如下:
    // 练习1
    let ex1 = () => {
        return fp.map(fp.add(1), maybe.map(x => x)._value)
    }
    console.log(ex1())  //[ 6, 7, 2 ]
    
    练习2:实现一个函数ex2,能够fp.first获取列表的第一个元素
    练习2-题目.png
    解答:获取列表的第一个元素实现如下:
    //练习2
    let xs = Container.of(['do', 'ray', 'me', 'fa', 'so', 'la', 'ti', 'do'])
    
    let ex2 = () => {return fp.first(xs.map(x => x)._value)}
    console.log(ex2())  //do
    
    练习3:实现一个函数ex3,使用safeProp和fp.first找到user的名字的首字母
    练习3-题目.png
    解答:使用safeProp和fp.first找到user的名字的首字母实现如下:
    // 练习3
    let safeProp = fp.curry(function (x, o){
        return Maybe.of(o[x])
    })
    let user = {id: 2, name: 'Albert'}
    let ex3 = () => {
        return fp.first(safeProp(Object.keys(user).indexOf('name'),Object.values(user))._value)
    }
    console.log(ex3()) //A
    
    练习4:使用MayBe重写ex4,不要有if语句
    练习4.png
    // 练习4
    let ex4 = function (n) {
        if(n){
            return(parseInt(n))
        }
    }
    
    let ex5 = n =>{
        return Maybe.of(n)._value 
    }
    
    let ex6 = n =>{
        return !!n? Maybe.of(n)._value : undefined
    }
    console.log(ex4(''))
    console.log(ex5(''))
    console.log(ex6(''))
    注:ex5的写法会在空字符串和null的时候导致输出和ex4,ex6不一样
    

    四、手写实现MyPromise源码

    要求:尽可能还原Promise中的每一个API,并通过注释的方式描述思路和原理

    MyPromise源码(myPromise.js)
    /*由于这个状态频繁使用,为了使用这个常量时编辑器有代码提示并能够复用,故把它定义为常量*/
    const PENDING = 'pending'  //等待
    const FULFILLED = 'fulfilled'  //成功
    const REJECTED = 'rejected'  //失败
    
    class MyPromise{
        //构造函数  ==》 立即执行执行器  ==》 指的是传递过来的回调函数
        constructor(executor) {
    
            // 执行器错误处理 当执行器中代码在执行过程中发生错误的时候,这个时候就让promise状态变成失败
            try{
                executor(this.resolve, this.reject)
            }catch (e) {
                //捕获执行器的错误
                this.reject(e)
            }
        }
    
        /*状态是每个promise对象独有的,故因该把状态属性定义为实例属性*/
        status = PENDING   //promise状态  ===》 默认值为等待
    
        //由于每个promise对象都有自己成功之后的值,都有自己失败的原因,故应该把这两个属性定义为实例的属性
        value = undefined  //成功之后的值
        reason = undefined //失败后的原因
    
        //由于then方法可能会被多次调用,联想到数组能够同时存储多个函数 故在这里将属性定义为数组
        successCallback = [] //成功回调
        failCallback = []    //失败回调
    
        //定义为箭头函数的目的:将来在直接调用某个普通函数时,这个函数的this指向是window或者undefined,为了能让this的指向为类的实例对象即promise对象,故而使用箭头函数
        resolve = value => {
    
            //为了确保状态确定后就不可更改,需加以判断
            //如果状态不是等待,阻止程序向下执行
            if(this.status !== PENDING) return
    
            //将状态更改为成功
            this.status = FULFILLED
    
            //将传递过来的值进行赋值 ==》 保存成功后的值
            this.value = value
    
            //判断成功回调是否存在 如果存在 则调用并传递相应的参数
            //数组中存储了多个回调函数,我们需要循环遍历这个数组,并在循环的过程中调用这个回调函数
            //当数组的长度不为0时,就继续执行循环体中的代码
            //考虑到需要从前往后执行,故调用数组的shift方法,把前面的回调函数弹出来
            while(this.successCallback.length) this.successCallback.shift()()
        }
    
        reject = reason => {
    
            //为了确保状态确定后就不可更改,需加以判断
            //如果状态不是等待,阻止程序向下执行
            if(this.status !== PENDING) return
    
            //将状态更改为失败
            this.status = REJECTED
    
            //将传递过来的值进行赋值 ==》 失败后的原因
            this.reason = reason
    
            //判断失败回调是否存在 如果存在 则调用并传递相应的参数
            //数组中存储了多个回调函数,我们需要循环遍历这个数组,并在循环的过程中调用这个回调函数
            //当数组的长度不为0时,就继续执行循环体中的代码
            //考虑到需要从前往后执行,故调用数组的shift方法,把前面的回调函数弹出来
            while(this.failCallback.length) this.failCallback.shift()()
        }
    
        //then要被定义在原型对象中,并接受成功回调和失败回调两个参数
        then (successCallback, failCallback){
    
            //在调用then方法不传递任何参数的时候,要将最先的成功状态依次传递给有回调函数的then方法
            successCallback = successCallback? successCallback : value => value
            failCallback = failCallback? failCallback : reason => {throw reason}
    
            //then要实现链式调用,then方法必须返回promise对象,上一个回调的返回值传递给下一个then成功的回调
            let promise2 = new MyPromise((resolve, reject)=>{
    
                //判断状态并调用对应的回调函数并传递相应的参数
                if(this.status === FULFILLED){
    
                    //由于promise2还没被实例完,在实例过程中获取不到,故使用异步实现,让同步代码先实现,再来执行异步代码,这时候就能获取到promise2
                    setTimeout(()=>{
    
                        //then方法中的回调函数在执行过程中报错,这个错误要在下一个then的reject中捕获到
                        try{
                            let x = successCallback(this.value)
                            resolvePromise( promise2, x, resolve, reject)
                        }catch (e) {
                            //捕获then回调的错误
                            reject(e)
                        }
                    }, 0)
                }else if(this.status ===REJECTED){
    
                    //由于promise2还没被实例完,在实例过程中获取不到,故使用异步实现,让同步代码先实现,再来执行异步代码,这时候就能获取到promise2
                    setTimeout(()=>{
    
                        // then方法中的回调函数在执行过程中报错,这个错误要在下一个then的reject中捕获到
                        try{
                            let x = failCallback(this.reason)
                            resolvePromise( promise2, x, resolve, reject)
                        }catch (e) {
                            //捕获then回调的错误
                            reject(e)
                        }
                    }, 0)
                }else{
    
                    //说明当前状态等待,但不知是调用成功还是失败的回调
                    //故将成功回调和是失败回调存储起来
                    this.successCallback.push(() => {
                        successCallback()
                        setTimeout(()=>{
                            try{
                                let x = successCallback(this.value)
                                resolvePromise( promise2, x, resolve, reject)
                            }catch (e) {
                                //捕获then回调的错误
                                reject(e)
                            }
                        }, 0)
                    })
                    this.failCallback.push(() => {
                        setTimeout(()=>{
                            try{
                                let x = failCallback(this.reason)
                                resolvePromise( promise2, x, resolve, reject)
                            }catch (e) {
                                //捕获then回调的错误
                                reject(e)
                            }
                        }, 0)
                    })
                }
            });
            return promise2
        }
    
        //无论当前这个promise对象最终的状态是成功还是失败,finally中的这个回调函数始终都会执行一次e
        //在finally方法的后面可以链式的调用then方法拿到当前这个promise对象返回的结果
        finally (callBack){
            //如何得到当前promise对象的状态  ==》 this.then方法可以
            return this.then(value=>{
                //在finally中return了一个promise对象
                return MyPromise.resolve(callBack()).then(()=>value)
            },reason=>{
                return MyPromise.resolve(callBack()).then(()=> {throw reason})
            })
        }
    
        //用于当前promise对象失败的情况,如果没有传递失败的回调函数,则会被catch捕获到
        catch(failCallback){
            return this.then(undefined, failCallback)
        }
    
        // all方法是用来解决异步并发问题的,它允许我们按照异步代码调用的顺序得到异步执行的结果
        // all的返回值也是一个promise对象,在后面可以链式对用then方法
        // 在all中的promise对象都是成功的,那么all最后的结果也是成功,如果有一个失败,那么结果就是失败的
        // 通过类调用,故为静态方法,该方法接收一个数组作为参数
        static all (array){
            let results = []
            let index = 0
    
            return new MyPromise((resolve, reject) => {
                function addData(key, value) {
                    results[key] = value
                    index++
                    // 针对异步情况下,判断index的值和数组的长度相等,说明数组中所有的内容都执行完了,从而而决定是否调用resolve回调函数
                    if(index === array.length){
                        resolve(results)
                    }
                }
    
                //循环该数组
                for(let i = 0; i < array.length; i++){
                    let current = array[i]
                    if(current instanceof MyPromise){
                        //promise对象,若成功的话将成功的值添加到数组中,若有一个失败的话失败的话则将失败的原因通过reject回调
                        current.then(value => addData(i, value), reason => reject(reason))
                    }else{
                        //普通值 则直接添加到数组中
                        addData(i, array[i])
                    }
                }
    
            })
        }
    
        //如果是普通值,则创建一个promise对象,被将这个值包裹在promise对象中,然后把创建出来的promise对象作为resolve方法的返回值,才能在后面链式调用then方法
        //如果是promise对象,则原封不动的将这个promise对象再作为resolve方法的返回值,所以才能在后面调用then方法,通过then方法的成功回调拿到这个promise对象的返回值
        static  resolve (value){
            if(value instanceof  MyPromise) return value
            return new MyPromise(resolve => resolve(value))
        }
    }
    
    //判断 x 值时普通值还是promise对象
    //如果是普通值,直接调用resolve
    //如果是promise对象 查看promise对象返回的结果
    //再根据promise对象返回的结果 决定调用resolve 还是调用reject
    function resolvePromise(promise2, x, resolve, reject){
        //相等表示自己返回自己(Promise对象自返回),这时应该调用reject回调函数
        if(promise2 === x){
            return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
        }
        if( x instanceof  MyPromise){
            //promise对象
            x.then(resolve,reject)
        }else{
            //普通值
            resolve(x)
        }
    }
    
    //导出当前类
    module.exports = MyPromise;
    
    
    测试代码(index.js)
    /**
     * 了解promise原理及原理代码实现
     * 1.Promise 就是一个类 在执行这个类的时候 需要传递一个执行器进去 执行器会立即执行 故放在promise类的构造器中
     * 2.Promise 中有三种状态 分别为 成功(fulfilled) 失败(rejected) 等待(pending)
     *  pending -> fulfilled
     *  pending -> rejected
     ** 一旦状态确定就不可更改
     * 3.resolve和reject函数是用来更改状态
     * resolve:fulfilled
     * reject:rejected
     * 4.then方法内部做的事情就是判断状态 如果状态成功 调用成功的回调函数 如果状态失败 调用失败的回调函数 then被定义为原型对象当中
     * 5.then成功回调有一个参数 表示成功之后的值 then失败回调有一个参数 表示失败的原因
     **/
    //导向MyPromise
    const MyPromise = require('./myPromise')
    
    //创建promise对象    resolve  reject 两个函数参数
    let promise = new Promise((resolve, reject) => {
        //把状态变成成功 参数为成功后的值
        resolve()
    
        //把状态编程失败  参数为失败的原因
        reject()
    })
    
    //需实现promise的then方法,要先了解其中传递两个回调函数及其含义
    //调用then方法时,首先要去判断promise状态,成功的话则调用成功回调函数,失败的话则调用失败回调函数
    //由于then能被任意一个promise对象调用,故应该将它定义在原型对象中
    //then成功回调有一个参数(value) 表示成功之后的值 then失败回调有一个参数(reason) 表示失败的原因
    promise.then(value=>{},reason=>{})
    
    
    /** 1.类核心逻辑实现调用 **/
    /*let promise1 = new MyPromise((resolve, reject) => {
        resolve('成功')
    
        // reject('失败')
    })
    
    promise1.then(value => {
        console.log(value)  // 成功
    }, reason => {
        console.log(reason)  // 失败
    })*/
    
    /** 2.在Promise类中加入异步逻辑 **/
    /*let promise2 = new MyPromise((resolve, reject) => {
        setTimeout(() => {
            resolve('成功')
        },2000)
    
        // reject('失败')
    })
    
    promise2.then(value => {
        console.log(value)  // 等待2s后输出成功
    }, reason => {
        console.log(reason)  // 等待2s后输出失败
    })*/
    
    /** 3.实现then方法多次调用添加多个处理函数 **/
    /*let promise3 = new MyPromise((resolve, reject) => {
        resolve('成功')
    
        // reject('失败')
    })
    
    promise3.then(value => {
        console.log(1)  // 1
        console.log(value)  // 成功
    }, reason => {
        console.log(reason)  // 失败
    })
    
    promise3.then(value => {
        console.log(2)  // 2
        console.log(value)  // 成功
    }, reason => {
        console.log(reason)  // 失败
    })
    
    promise3.then(value => {
        console.log(3)  // 3
        console.log(value)  // 成功
    }, reason => {
        console.log(reason)  // 失败
    })*/
    
    /** 4./5.实现then方法的链式调用 **/
    //后面then方法拿到的值实际上是上一个回调函数的返回值
    /*let promise4 = new MyPromise((resolve, reject) => {
        resolve('成功')
    
        // reject('失败')
    })
    //测试4 then中返回值的情况
    promise4.then(value => {
        console.log(value)  // 成功
        return 100
    }).then(value => {
        console.log(value)
    })
    //测试5  then中返回promise情况
    function other(){
        return new MyPromise((resolve, reject) => {
            resolve('other')
        })
    }
    promise4.then(value => {
        console.log(value)  // 成功
        return other()
    }).then(value => {
        console.log(value)  // other
    })*/
    
    /** 6.then方法链式调用识别Promise对象自返回 **/
    /*let promise6 = new MyPromise((resolve, reject) => {
        resolve('成功')
        // reject('失败')
    })
    
    let p6 = promise6.then(value => {
        console.log(value)
        return p6
    })
    
    p6.then(value => {
        console.log(value)  //成功
    },reason => {
        console.log(reason.message)  //Chaining cycle detected for promise #<Promise>
    })*/
    
    /** 7.捕获错误及then链式调用其他状态代码补充 **/
    // 执行器错误   then方法中的回调函数在执行过程中报错,这个错误要在下一个then的reject中捕获到
    /*let promise7 = new MyPromise((resolve, reject) => {
        // throw new Error('executor error')
        // resolve('成功')
        reject('失败')
    })
    
    promise7.then(value => {
        console.log(value)  //成功
    },reason => {
        console.log(reason.message)  //executor error
    })
    
    promise7.then(value => {
        console.log(value)  //成功
        throw new Error('then error')
    },reason => {
        console.log(reason.message)  //executor error
        return 10000
    }).then(value => {
        console.log(value)  // 成功  10000
        // throw new Error('then error')
    },reason => {
        console.log('xxx')   //xxx
        console.log(reason.message)  //then error
    })*/
    
    /** 8.then中方法编程可选参数 **/
    
    /*let promise8 = new MyPromise((resolve, reject) => {
        resolve('成功')
        // reject('失败')
    })
    promise8.then().then().then(value =>
        console.log(value) //成功  失败
    )*/
    
    
    function p1() {
        return new MyPromise((resolve, reject) => {
            setTimeout(() => {
                resolve('p1')
            }, 2000)
        })
    }
    
    function p2() {
        return new MyPromise((resolve, reject) => {
            // resolve('p2')
            reject('失败')
        })
    }
    
    /** 9.promise.all方法的实现 **/
    /*MyPromise.all(['a', 'b', p1(), p2(), 'c']).then(result =>
        console.log(result)  // [ 'a', 'b', 'p1', 'p2', 'c' ]
    
    )*/
    
    /** 10.promise.resolve方法的实现 **/
    /*MyPromise.resolve(100).then(value => console.log(value))
    MyPromise.resolve(p1()).then(value => console.log(value))*/
    
    /** 10.promise.finally方法的实现  **/
    /*p2().finally(()=>{
        console.log('finally')
        return p1()
    }).then(value=>{
        console.log(value)  // p2
    },reason=>{
        console.log(reason)
    })*/
    
    /** 11.promise.catch方法的实现 **/
    /*p2().then(value => console.log(value))
        .catch(reason => console.log(reason))*/
    

    相关文章

      网友评论

          本文标题:Part1.模块一:函数式编程与 JS 异步编程、手写 Prom

          本文链接:https://www.haomeiwen.com/subject/nmrrkktx.html