Promise学习笔记

什么是Promise?

    1、抽象表达:是JavaScript中进行异步编程的新的解决方案(旧的指的是纯回调式的用法)。

    2、具体表达:

        (1)从语法上来说:promise是一个构造函数

        (2)从功能上来说:promise对象用来封装一个异步操作并且可以获取其结果

Promise的状态改变

promise一共有三个状态:pending、resolved、rejected。

    1、pending变为resolved

    2、pending变为rejected

        说明:pending变化的状态只有这俩种,且一个promise对象只能改变一次,无论变为成功还是失败,都只会有一个结果数据,成功的结果数据一般称为value,失败的数据结果一般称为reason。

promise操作流程图


promise操作流程图

写一个基本的promise操作:

 /*            

简单的promise操作流程:

                1、创建一个新的promise对象

                2、执行一个异步任务

                3、判断异步操作成功与否:

                    3.1、成功:调用resolve(value) 

                   3.2、失败:调用reject(reason) 

       */
    const p = new Promise((resolve,reject) =>{ // 创建一个新的promise对象 ,相当于一个执行器函数

            // 执行一个异步操作任务

            setTimeout(() => { 

                const time = Date.now() // 生成一个现在的时间

                if (time %2 == 0) {

                    // 表示成功,调用resolve(value)

                    resolve("成功的数据是 "+time)

                } else {

                    // 表示失败,调用reject(reason)

                    reject('失败的数据是 '+time)

                }

            },1000)

        })

        p.then(

            value => {  //接收得到成功的数据

                console.log('成功的回调 ' + value)

            },

            reason => {    //接收得到失败的数据

                console.log('失败的回调' + reason)

            }

        )

为什么要用Promise

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

        1、旧的:必须在启动异步任务之前指定。

        2、promise:启动异步任务 => 返回promise对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个)


例1——纯回调函数实现

    // 使用纯回调函数实现一个回调

        function successCallback(result){   //手动创建一个成功的回调函数

            console.log('声音文件创建成功:' + result)

        }

        function failureCallback(error){

            console.log('声音文件创建失败:' + error)

        }

        createAudioFileAsync(audioSetting,successCallback,failureCallback)  //创建一个创建音频的异步任务

        /*

            1、使用纯回调函数首先要定义好俩个回调函数再去启动异步任务

       如果使用promise的话,指定回调函数的方式更加灵活,不一定要在执行器函数之前就设置回调函数,可以在启动异步任务之后,甚至可以在有了结果之后再设定回调函数

        */

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

        1、什么是回调地狱? 

            多个串联的异步操作,就会出现回调地狱,通常还以上个回调函数的结果进行处理

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

        2、回调地狱的缺点

            不方便阅读,不方便异常处理

例:简单的地狱回调的形式

         doSomething(function(result){   //这个函数调用后结果为result,传给下一层函数
            doSomethingElse(result,function(newResult){     //把上层的result作为条件,再指定成功的回调和失败的回调成功的回调会生成全新的结果newResult

                doThirdThing(newResult,function(finalResult){   //把上层成功回调的结果再拿来当做条件,给他设置成功回调和失败回调

                    console.log('回调地狱的简单模板,多个异步操作串联')

                },failureCallback)

            },failureCallback)

        },failureCallback)

采用promise的链式调用解决回调地狱问题

    优点:1、代码可阅读性高

                2、统一异常处理,异常处理方便

        // 采用promise的链式调用解决回调地狱

        doSomething()   //  得到promise对象,启动异步任务(一个promise对应一个异步任务)

        .then(function(result){     //成功的回调result,调用第二个异步任务,返回一个新的promise 

            return doSomethingElse(result)  //把这个result结果作为成功传递给下一层的异步任务

        })

        .then(function(newResult){  //获取到doSomethingElse的成功回调newResult,并且继续向下传递

            return doThirdThing(newResult)

        })

        .then(function(finalResult){ //获取到doThirdThing的成功回调finalResult

            console.log('使用promise的链式形式解决回调地狱') // final成功回到的结果

        })

        .catch(failureCallback) // 统一处理异常,称为异常传透

 3、解决方案

            async/await

使用async/await解决终极解决回调地狱的问题

        async function request(){

            try{

                const result = await doSomething()

                const newResult = await doSomethingElse(result)

                const finalResult = await doThirdThing(newResult)

                console.log('用async/await终极解决回调地狱问题'+ result + newResult + finalResult)

            } catch(error){

                console.log(error)

            }

        }

Promise的API(语法)

        1、Promise构造函数:promise(excutor){}

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

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

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

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

        2、Promise.prototype.then方法:(onResolved,onRejected) => {}

            onResolved函数:成功的回调函数  (value) => {}

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

        说明:指定用于得到成功value的成功回调和用于得到失败reason的失败回调。

              返回一个新的promise对象   


        3、Promise.prototype.catch方法:(onRejected) => {}

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

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

        4、Promise.resolve方法: (value) => {}

            value:成功的数据或promise对象

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

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

            reason:失败的原因

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

        6、Promise.all方法:(promise) => {}

            promise:包含n个promise的数组

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

        7、Promise.race方法:(promise) => {}

            promises:包含n个promise的数组

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

Promise的异常抛出

    promise也可以使用异常抛出,抛出后promise的状态为rejected

        const p = new Promise((resolve,reject) => {

            // resolve(1)    promise变为resolved成功的返回状态

            // reject(2)    promise变为rejected失败的返回状态

            // throw new error('出错了')    抛出异常,promise变成rejected失败状态,reason为 抛出的异常

            throw 3

        })

        p.then(

            value => {

            },

            reason => {

                console.log('reason ' + reason)

            }

        )

promise状态和指定回调函数先后问题

 (1)都有可能,正常情况下时先指定回调再改变状态,但也可以先改变状态再去指定回调

            (2)如何先改变状态再指定回调?

                1、在执行器中直接调用resolve()/reject()

                2、延迟更长时间才调用then()

            (3)什么时候才能得到数据

                1、如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据

                2、如果先改变状态,那当指定回调时,回调函数就会调用,得到数据

例:先指定回调函数,后改变状态值

        new Promise((resolve,reject) => {

            setTimeout(() => {

                reject(1)  // 后改变状态(同时指定数据),异步执行回调函数

            },1000)

        }).then(    // 先指定回调函数,保存当前指定的回调函数

            value => {},

            reason => {console.log('reason', reason)}

        )

例:先改变状态值,后指定回调函数

        new Promise((resolve, reject) => {

            resolve(1)  // 先改变的状态(同时指定数据)

        }).then(    // 后指定回调函数,异步执行回调函数

            value => {

                console.log('value2',value)

            }

        )

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

    (1)简单表述:由then()指定的回调函数执行的结果决定

    (2)详细表达:

        1、如果抛出异常,新promise变为rejected,reason为抛出的异常

        2、如果返回的是非promise的任意值,新promise变为resolved,value为返回的值

        3、如果返回的是另一个新promise,次promise的结果就会成为新promise的结果

Promise异常传透

    (1)当使用promise的then链式调用时,可以在最后指定失败的回调

    (2)当前面任何操作出了异常,都会传到最后的回调中处理

    中断promise链

        (1)当使用promise的then链式调用时,在中间中断,不在调用后面的回调函数

        (2)办法:在回调函数中返回一个pendding状态的promise对象


自定义(手写)promise

才艺展示级别,学不会了,等啥时候我觉的我行了我再来学学看!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335