解读Es6之 promise

        单线程:  在同一时间只能有同一任务进行。JavaScript就是一门单线程语言
                当有多个任务需要进行时,则需要进行排队,前一个执行完毕才能执行下一个;
                当前一个任务报错后,则不进行下一个
        案例如下:
    // 1、同步
    function fun1(){
        console.log(1) 
        // throw Error("121212") // 错误时,则不向后进行
    }
    function fun2(){
        console.log(2)
    }
    function fun3(){
        console.log(3)
    }
    // fun1()
    // fun2()
    // fun3()

    /* 正确时输出
        1
        2
        3

       错误时输出
        解读promise.html:23 Uncaught Error: 121212
        at fun1 (解读promise.html:23)
        at 解读promise.html:31
    */
View Code
/*
      为什么要使用单线程语言?
            js是被设计在浏览器中使用的,浏览器多用于数据等的展示、更改等。 

            若有多个线程同时进行,如:

            数据1: “嘿嘿嘿,我是页面上的数据1,我的真实名字叫山本,我就是这么自信的数据” (页面数据)
            线程1: “二营长,你tm的意大利炮,给我干山本一炮” (对数据删除操作)
            线程2: “二营长,活捉山本”(对数据进行修改)
            浏览器:“身为二营长的我,太南了” (浏览器不知执行哪歩操作)
            
            这样,浏览器就会一脸闷逼。

            所以,js被设计为单线程,即可给山本一炮,干不死,再活捉!

            (最近独立团看多了,哈哈,简单比喻下吧)
    */ 
View Code
/*
        异步:即同时进行,当某个任务存在ajax等异步操作时,不必执行完才会执行下一个,如下
     */ 
// 2、异步
    function fun4(){
        console.log(4)
    }
    function fun5(){
        setTimeout(()=>{
            console.log(5)
        },0)
    }
    function fun6(){
        console.log(6)
    }
    // fun4()
    // fun5()
    // fun6()

    /* 输出
        4
        6
        5
    */ 
View Code
/*
        异步编程,
        1、使用回调函数
        2、使用es6的promise ( 重点讲解 )
    */ 
// Promise

    /*
        1、检查当前浏览器是否支持promise
            typeof(Promise)==="function"  

        2、三种状态
            pending(进行中)、fulfilled(已成功)和rejected(已失败)

        3、可以使异步操作变同步


    */ 

    /*
        基本使用:
        参数为js引擎自带
        resolve : 将pending状态转为 fulfilled状态
        reject :  将pending状态转为 rejected状态
    */ 
    let Promise_demo1 = new Promise((resolve, reject) => {
        let num = Math.floor( Math.random() * 10 )
        if (num > 5) { // 正确时 执行这个,并将参数传递出去
            resolve(num)
        } else { // 错误时,执行这个,可以支持任意参数
            reject(num + '错误了!')
        }
    })

    Promise_demo1
    .then( (data) => { // 表示 为成功状态时,要执行的,即通过 resolve 后执行
        // console.log(data)
    })
    .catch( (Error) => { // 表示 为失败状态时,要执行的,即通过 reject 后执行
        // console.log(Error)
    })

    // 以上通过 then catch ,也可只在then中执行,一个参数为成功时执行,第二个参数为失败时执行
    // Promise_demo1  
    // .then( (data) => {
    //     console.log(data)
    // }, (err) => {
    //     console.log(err)
    // } )


    // 通过函数使用promise
    function timeout(_time){
        let num = Math.floor( Math.random() * 10 )
        return new Promise( (resolve, reject) => {
            setTimeout(()=>{ resolve(num) },_time)
        } )
    }

    timeout(1000)
    .then( (data) => {
        // console.log(data) // 依次在1秒输出随机数 
    } )
    .catch( (err) => {} )

    /* 
        小插曲:
        Uncaught (in promise)
        期间,若报这个错,即reject发出错误,
        1、需要使用catch接收,即添加 .catch((e) => {})
        2、或,不使用reject返回错误
        为了严谨,推荐使用第一种
    */ 

    /*
        当既有promise执行,又有其他同步操作执行
        先 执行promise
        再 执行同步操作
        后 执行promise.then
        后 执行异步操作
        案例如下:
    */ 

    let Promise_demo2 = new Promise( (resolve, reject) => {
        // console.log("promise内支持的")
        resolve('promise成功后执行的')
    } )

    Promise_demo2
    .then( (data) => {
        // console.log(data)
    } )

    function func7(){
        // console.log('同步操作')
    }
    function func8(){
        setTimeout( ()=>{
            console.log("异步操作")
        },0 )
    }

    // func7()
    // func8()
    
    /* 输出
        promise内支持的
        同步操作
        promise成功后执行的
        异步操作
    */ 

    /*
        resolve, reject 不仅可以返回一个参数,还可以返回一个promise
        情况一: 参数的promise 的请求时间小于 调用者的promise请求时间
        以下输出:
        1秒后:Uncaught (in promise) 2121  ( 即先执行 .catch )
        3秒后:2121

        因为p1作为参数,在1秒后执行,p2在3秒后将p1作为参数传出去再执行
    */ 

    const p1 = new Promise(function (resolve, reject) {
        // setTimeout(() => reject('2121'), 1000)
    })

    const p2 = new Promise(function (resolve, reject) {
        // setTimeout(() => resolve(p1), 3000)
    })

    p2
    .then(result => console.log(result))
    .catch(error => console.log(error))

    /*
        情况二: 参数的promise 的请求时间 大于 调用者的promise请求时间
        以下输出:
        3秒后 Error: 错误了

        因为p4在1秒后状态改变,resolve返回的又是新的promise,导致p4的状态失效,p3的状态替换了p4的状态
    */ 

    const p3 = new Promise(function (resolve, reject) {
        // setTimeout(() => reject(new Error('错误了')), 3000)
    })

    const p4 = new Promise(function (resolve, reject) {
        // setTimeout(() => resolve(p3), 1000)
    })

    p4
    .then(result => console.log(result))
    .catch(error => console.log(error))

    /*
        .finally 不管是成功还是失败后,都会执行
    */ 

    let Promise_demo3 = new Promise( (resolve, reject) => {
        let num = Math.floor( Math.random() * 10 )
        if( num > 5 ) {
            // resolve('Oh Yeah')
        } else {
            // reject('Oh No')
        }
    } )

    Promise_demo3
    .then( data => console.log(data) )
    .catch( data => console.log(data) )
    .finally( () => console.log("I am finally") )  // 都会执行


    /*
        Promise.all()
        用于将多个Promise实例,包装成一个promise实例
        如 let p_all = Promise.all( [ promise1, promise2, promise3 ] );
        
        当所有参数返回resolve时, promise.all则返回resolve
        当有一个参数返回reject时,promise.all则返回reject

        如下:
    */ 

    let arrImg = ['img/0.jpg', 'img/1.jpg', 'img/2.jpg'];
    function loadImg(url){
        return new Promise( (resolve, reject) => {
            let img = new Image();
            // img.src = url;
            // img.onload = () => resolve(img); // 或 resolve(this)
            // img.onerror = () => reject('加载失败');
        } )
    }
    
    let PromiseAll = Promise.all( [ loadImg(arrImg[0]), loadImg(arrImg[1]), loadImg(arrImg[2]) ] )
    // 若将其中的一个改为不存在的路径时,则会报错 如将loadImg(arrImg[0])改为  loadImg(arrImg[3]),
    PromiseAll
    .then( images => {
        // images.forEach(value => document.body.appendChild(value))
    } )
    .catch( data => console.log(data,'错误时提示') )
    .finally( () => console.log('程序运行完成') )
    

    /*
        Promise.race() 参数均为promise
        const p = Promise.race([p1, p2, p3]);        
        当其中一个参数的状态改变时,p的状态就会改变
    */ 


    /*
        Es2020 新加  Promise.allSettled() 
        const p_allSe = Promise.allSettled([p1, p2, p3]);  
        可能部分浏览器暂时不支持,
        使用场景:不关心异步操作的结果,只关心这些操作有没有结束 
    */ 

        // let p_allSe = Promise.allSettled([p3, p4])
        // p_allSe.then( result => console.log( result ) )



    /*
        Promise.resolve()
        将现有对象转为 Promise 对象

        不知实际项目中能解决什么问题,有大神知道的可以回复下
    */ 


    /*
        Promise.reject()
    */ 

    // let p_reject = Promise.reject(new Error('12121'))
    // p_reject.catch((err)=> console.log(err)) // 报出错误来

    /*
        Promise.try()
    */ 

    // 将两个或多个含有异步操作的函数 同步执行

    function func9(){
        return new Promise( resolve => {
            setTimeout(() => {
                console.log(9)
                resolve()
            },1000)
        } )
    }
    function func10(){
        console.log(10)
    }
    func9().then( ()=>func10() )

    // 
    function func9(){
        setTimeout(() => {
            console.log(9)
        },1000)
    }
    function func10(){
        console.log(10)
    }

    
View Code

 

posted @ 2019-12-14 15:49  王希有  阅读(403)  评论(1编辑  收藏  举报