promise 订阅
《Promise》是李玟于2001年10月13日发行的音乐专辑,共收录13首歌曲,由李振权、周杰伦等人担任制作人。2002年,专辑歌曲《So Crazy》获得第8届华语音乐榜中榜最受欢迎歌曲奖 [1]  。 展开全文
《Promise》是李玟于2001年10月13日发行的音乐专辑,共收录13首歌曲,由李振权、周杰伦等人担任制作人。2002年,专辑歌曲《So Crazy》获得第8届华语音乐榜中榜最受欢迎歌曲奖 [1]  。
信息
专辑歌手
李玟
制作人
李振权,周杰伦
专辑语言
普通话,粤语
曲目数量
13首
发行时间
2001年10月13日
音乐风格
流行
发行地区
中国
外文名称
Promise
唱片公司
索尼音乐
Promise创作背景
因为李玟在筹备、推出该专辑的时候,已经出道九年了。在此期间,她通过努力迈向国际,也创造了音乐成绩。她希望通过该专辑,将她的音乐心情与听众分享,因此为专辑取名《Promise》。为了展现出专辑的摇滚曲风和她的音乐实力,李玟亲自参与创作了多首歌曲 [2]  。为了写歌,李玟自创“录音机创作法”的方式进行创作,通过录音机录下哼唱的旋律,再通过钢琴将音符弹奏出来 [3]  。此外,专辑制作阵容包括李振权及周杰伦等人 [4]  。《Baby,对不起》由李玟亲自参与填词。当时,李玟在翻阅学生时代的随身笔记本时,看到了她恋爱时的心情手记,于是有感而发创作出该曲。在演唱该曲时,李玟投入了真情实感 [5]  。《刀马旦》是周杰伦为李玟量身订做的歌曲。因为录制该曲的过程中产生了很多灵感,所以李玟和周杰伦两人从晚上5点进棚录音,一直唱到了第二天早上8点。期间,周杰伦还在歌曲中即兴客串了Rap [6]  。因为李玟偏好热辣舞曲风格的歌曲,所以她特意向香港音乐人雷颂德邀歌,得到了一首粤语歌曲《好来好往》 [3]  。
收起全文
精华内容
下载资源
问答
  • Promise

    千次阅读 2019-11-26 17:18:11
    Promise

    pending
          prep. 在等待…时期;直到…为止
          adj. 待定;待决;即将发生的
          v. 吊着;悬而未决;待决


    resolve
          v. 解决(问题或困难);决心;决定;作出决定;作出决议;表决
          n. 决心;坚定的信念


    reject
          v. 拒绝接受;不予考虑;拒收;不录用;拒绝接纳;(因质量差)不用,不出售,不出版
          n. 废品;次品;不合格者;被剔除者;被拒收者


    1 Promise的理解和使用

    Promise是什么

    1.抽象表达: 
        Promise是JS中进行异步编程的新的解决方案(旧的是谁?)
    2.具体表达:
        从语法上来说: Promise是一个构造函数
        从功能上来说: promise对象用来封装一个异步操作并可以获取其结果
    3. promise的状态改变(只有2种, 只能改变一次)
        pending变为resolved
        pending变为rejected
    4. promise的基本流程

    为什么要用Promise  

    1. 指定回调函数的方式更加灵活: 可以在请求发出甚至结束后指定回调函数
    2. 支持链式调用, 可以解决回调地狱问题
    // 1. 创建一个新的promise对象
    const p = new Promise((resolve, reject) => {// 执行器函数  同步回调
        console.log('执行 excutor')
        // 2. 执行异步操作任务
        setTimeout(() => {
            const time = Date.now() // 如果当前时间是偶数就代表成功, 否则代表失败
            // 3.1. 如果成功了, 调用resolve(value)
            if (time % 2 === 0) {
                resolve('成功的数据, time=' + time)
            } else {
                // 3.2. 如果失败了, 调用reject(reason)
                reject('失败的数据, time=' + time)
            }
        }, 1000);
    
    })
    console.log('new Promise()之后')
    
    setTimeout(() => {
        p.then(
            value => { // 接收得到成功的value数据    onResolved
                console.log('成功的回调', value)
            },
            reason => {// 接收得到失败的reason数据  onRejected
                console.log('失败的回调', reason)
            }
        )
    }, 2000);


    2 为什么要用Promise

    https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Using_promises

    /* 
      1. 指定回调函数的方式更加灵活: 
        旧的: 必须在启动异步任务前指定
        promise: 启动异步任务 => 返回promie对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束后指定)
    
      2. 支持链式调用, 可以解决回调地狱问题
        什么是回调地狱? 回调函数嵌套调用, 外部回调函数异步执行的结果是嵌套的回调函数执行的条件
        回调地狱的缺点?  不便于阅读 / 不便于异常处理
        解决方案? promise链式调用
        终极解决方案? async/await
      */
    // 成功的回调函数
    function successCallback(result) {
        console.log("声音文件创建成功: " + result);
    }
    // 失败的回调函数
    function failureCallback(error) {
        console.log("声音文件创建失败: " + error);
    }
    /* 1.1 使用纯回调函数 */
    createAudioFileAsync(audioSettings, successCallback, failureCallback)
    /* 1.2. 使用Promise */
    const promise = createAudioFileAsync(audioSettings); // 2
    setTimeout(() => {
        promise.then(successCallback, failureCallback);
    }, 3000);
    /* 
      2.1. 回调地狱
      */
    doSomething(function (result) {
        doSomethingElse(result, function (newResult) {
            doThirdThing(newResult, function (finalResult) {
                console.log('Got the final result: ' + finalResult)
            }, failureCallback)
        }, failureCallback)
    }, failureCallback)
    /* 
      2.2. 使用promise的链式调用解决回调地狱
      */
    doSomething()
        .then(function (result) {
            return doSomethingElse(result)//执行另一个异步任务,返回一个新的Promise
        })
        .then(function (newResult) {
            return doThirdThing(newResult)
        })
        .then(function (finalResult) {
            console.log('Got the final result: ' + finalResult)
        })
        .catch(failureCallback)//统一异常处理(异常传透)
    /* 
      2.3. 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. 主要API
        Promise构造函数: Promise (excutor) {}
        Promise.prototype.then方法: (onResolved, onRejected) => {}
        Promise.prototype.catch方法: (onRejected) => {}
        Promise.resolve方法: (value) => {}
        Promise.reject方法: (reason) => {}
        Promise.all方法: (promises) => {}
        Promise.race方法: (promises) => {}
    2. 几个重要问题
        如何改变promise的状态?
        一个promise指定多个成功/失败回调函数, 都会调用吗?
        promise.then()返回的新promise的结果状态由什么决定?
        改变promise状态和指定回调函数谁先谁后?
        promise如何串连多个操作任务?
        promise异常传(穿)透?
        中断promise链
    /*
      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方法: (promises) => {}
          promises: 包含n个promise的数组
          说明: 返回一个新的promise, 只有所有的promise都成功才成功, 只要有一个失败了就直接失败
      7. Promise.race方法: (promises) => {}
          promises: 包含n个promise的数组
          说明: 返回一个新的promise, 第一个完成的promise的结果状态就是最终的结果状态
    */
    new Promise((resolve, reject) => {
        setTimeout(() => {
            // resolve('成功的数据')
            reject('失败的数据')
        }, 1000)
    }).then(
        value => {
            console.log('onResolved()1', value)
        }
    ).catch(
        reason => {
            console.log('onRejected()1', reason)
        }
    )

     

    // 产生一个成功值为1的promise对象
    const p1 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(1)
        }, 100);
    })
    p1.then(value => {console.log(value)})//2
    const p2 = Promise.resolve(2)
    p2.then(value => {console.log(value)})//3
    const p3 = Promise.reject(3)
    p3.then(null, reason => {console.log(reason)})//1
    p3.catch(reason => {console.log(reason)})//1

     

    const p1 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(1)
        }, 100);
    })
    
    const p2 = Promise.resolve(2)
    
    const p3 = Promise.reject(3)
    // const pAll = Promise.all([p1, p2, p3])
    const pAll = Promise.all([p1, p2])
    pAll.then(
        values => {
            console.log('all onResolved()', values)
        },
        reason => {
            console.log('all onRejected()', reason)
        }
    )

    race
          n. 赛跑;速度竞赛;竞争;角逐;赛马会;种族;人种;血统
          v. (和…)比赛;参加比赛;使比赛;让…参加速度比赛;(使)快速移动,快速运转 

    const pRace = Promise.race([p1, p2, p3])
    pRace.then(
        value => {
            console.log('race onResolved()', value)
        },
        reason => {
            console.log('race onRejected()', reason)
        }
    )

    4 promise的几个关键问题

    /*
    1. 如何改变promise的状态?
      (1)resolve(value): 如果当前是pendding就会变为resolved
      (2)reject(reason): 如果当前是pendding就会变为rejected
      (3)抛出异常: 如果当前是pendding就会变为rejected
    
    2. 一个promise指定多个成功/失败回调函数, 都会调用吗?
      当promise改变为对应状态时都会调用
    */
    
    const p = new Promise((resolve, reject) => {
        // resolve(1) // promise变为resolved成功状态
        // reject(2) // promise变为rejected失败状态
        // throw new Error('出错了') // 抛出异常, promse变为rejected失败状态, reason为 抛出的error
        throw 3 // 抛出异常, promse变为rejected失败状态, reason为 抛出的3
    })
    p.then(
        value => {
        },
        reason => {
            console.log('reason', reason)
        }
    )
    p.then(
        value => {
        },
        reason => {
            console.log('reason2', reason)
        }
    )

     

    /*
    3.改变promise状态和指定回调函数谁先谁后?
      (1)都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调
      (2)如何先改状态再指定回调?
        ①在执行器中直接调用resolve()/reject()
        ②延迟更长时间才调用then()
      (3)什么时候才能得到数据?
        ①如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
        ②如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据
    */
    // 常规: 先指定回调函数, 后改变的状态
    new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(1) // 后改变的状态(同时指定数据), 异步执行回调函数
        }, 1000);
    }).then(// 先指定回调函数, 保存当前指定的回调函数
        value => {
        },
        reason => {
            console.log('reason', reason)
        }
    )
    // 如何先改状态, 后指定回调函数
    new Promise((resolve, reject) => {
        resolve(1) // 先改变的状态(同时指定数据)
    }).then(// 后指定回调函数, 异步执行回调函数
        value => {
            console.log('value2', value)
        },
        reason => {
            console.log('reason2', reason)
        }
    )
    console.log('-------') //先输出 异步执行
    
    //-------
    //value2 1
    const p = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(1) // 先改变的状态(同时指定数据), 异步执行回调函数
        }, 1000);
    })
    setTimeout(() => {
        p.then(
            value => {
                console.log('value3', value)
            },
            reason => {
                console.log('reason3', reason)
            }
        )
    }, 1100);

     

    /*
    4. promise.then()返回的新promise的结果状态由什么决定?
      (1)简单表达: 由then()指定的回调函数执行的结果决定
      (2)详细表达:
          ①如果抛出异常, 新promise变为rejected, reason为抛出的异常
          ②如果返回的是非promise的任意值, 新promise变为resolved, value为返回的值
          ③如果返回的是另一个新promise, 此promise的结果就会成为新promise的结果
    */
    new Promise((resolve, reject) => {
        // resolve(1)
        reject(1)
    }).then(
        value => {
            console.log('onResolved1()', value)
            // return 2
            // return Promise.resolve(3)
            // return Promise.reject(4)
            throw 5
        },
        reason => {
            console.log('onRejected1()', reason)
            // return 2
            // return Promise.resolve(3)
            // return Promise.reject(4)
            throw 5
        }
    ).then(
        value => {
            console.log('onResolved2()', value)
        },
        reason => {
            console.log(typeof reason);
            console.log('onRejected2()', reason)
        }
    )

     

    /*
    5.promise如何串连多个操作任务?
      (1)promise的then()返回一个新的promise, 可以开成then()的链式调用
      (2)通过then的链式调用串连多个同步/异步任务
    */
    new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log("执行任务1(异步)")
            resolve(1)
        }, 1000);
    }).then(
        value => {
            console.log('任务1的结果: ', value)
            console.log('执行任务2(同步)')
            return 2 //同步任务直接返回结果即可
        }
    ).then(
        value => {
            console.log('任务2的结果:', value)
    
            return new Promise((resolve, reject) => { //异步任务需要再次创建Promise对象并返回
                // 启动任务3(异步)
                setTimeout(() => {
                    console.log('执行任务3(异步))')
                    resolve(3)
                }, 1000);
            })
        }
    ).then(
        value => {
            console.log('任务3的结果: ', value)
        }
    )

    执行任务1(异步)
    任务1的结果:  1
    执行任务2(同步)
    任务2的结果: 2
    执行任务3(异步))
    任务3的结果:  3 


    /*
    6.promise异常传/穿透?
      (1)当使用promise的then链式调用时, 可以在最后指定失败的回调,
      (2)前面任何操作出了异常, 都会传到最后失败的回调中处理
    7.中断promise链?
      (1)当使用promise的then链式调用时, 在中间中断, 不再调用后面的回调函数
      (2)办法: 在回调函数中返回一个pendding状态的promise对象
    */
    new Promise((resolve, reject) => {
        // resolve(1)
        reject(1)
    }).then(
        value => {
            console.log('onResolved1()', value)
            return 2
        },
        // reason => {throw reason}
    ).then(
        value => {
            console.log('onResolved2()', value)
            return 3
        },
        reason => {
            throw reason
        }
    ).then(
        value => {
            console.log('onResolved3()', value)
        },
        reason => Promise.reject(reason)
    ).catch(reason => {
        console.log('onReejected1()', reason)
        // throw reason
        // return Promise.reject(reason)
        return new Promise(() => {
        }) // 返回一个pending的promise  中断promise链
    })
    new Promise((resolve, reject) => {
        reject(1)
    }).then(
        value => {
            console.log('onResolved1()', value)
        }
    ).catch(reason => {
        console.log('onReejected1()', reason)
        // throw reason
        return Promise.reject(reason)
        // return new Promise(() => {
        // }) // 返回一个pending的promise  中断promise链
    }).then(
        value => {
            console.log('onResolved2()', value)
        },
        reason => {
            console.log('onReejected2()', reason)
        }
    )
    
    // onReejected1() 1
    // onReejected2() 1

     

    展开全文
  • promise

    千次阅读 2018-10-24 21:52:06
    promise

    promise

    展开全文
  • ES6 Promise用法小结

    万次阅读 多人点赞 2018-07-25 10:42:49
    1.什么是Promise reject的用法 catch的用法 all的用法 race的用法 1.什么是Promise Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch...

    目录

    1.什么是Promise

    reject的用法

    catch的用法

    all的用法

    race的用法


    1.什么是Promise

    Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。(ps:什么是原型:https://blog.csdn.net/qq_34645412/article/details/105997336

    Promise对象有以下两个特点。

    (1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

    (2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

    下面先 new一个Promise

    let p = new Promise(function(resolve, reject){
    		//做一些异步操作
    		setTimeout(function(){
    			console.log('执行完成Promise');
    			resolve('要返回的数据可以任何数据例如接口返回数据');
    		}, 2000);
    	});

    刷新页面会发现控制台直接打出

    其执行过程是:执行了一个异步操作,也就是setTimeout,2秒后,输出“执行完成”,并且调用resolve方法。

    注意!我只是new了一个对象,并没有调用它,我们传进去的函数就已经执行了,这是需要注意的一个细节。所以我们用Promise的时候一般是包在一个函数中,在需要的时候去运行这个函数,如:

    <div onClick={promiseClick}>开始异步请求</div>
    
    const promiseClick =()=>{
    	 console.log('点击方法被调用')
    	 let p = new Promise(function(resolve, reject){
    		//做一些异步操作
    		setTimeout(function(){
    				console.log('执行完成Promise');
    				resolve('要返回的数据可以任何数据例如接口返回数据');
    			}, 2000);
    		});
            return p
    	}

    刷新页面的时候是没有任何反映的,但是点击后控制台打出

    当放在函数里面的时候只有调用的时候才会被执行

    那么,接下里解决两个问题:

    1、为什么要放在函数里面

    2、resolve是个什么鬼

    我们包装好的函数最后,会return出Promise对象,也就是说,执行这个函数我们得到了一个Promise对象。接下来就可以用Promise对象上有then、catch方法了,这就是Promise的强大之处了,看下面的代码:

    promiseClick().then(function(data){
        console.log(data);
        //后面可以用传过来的数据做些其他操作
        //......
    });

    这样控制台输出

    先是方法被调用起床执行了promise,最后执行了promise的then方法,then方法是一个函数接受一个参数是接受resolve返回的数据这事就输出了‘要返回的数据可以任何数据例如接口返回数据’

    这时候你应该有所领悟了,原来then里面的函数就跟我们平时的回调函数一个意思,能够在promiseClick这个异步任务执行完成之后被执行。这就是Promise的作用了,简单来讲,就是能把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。

    你可能会觉得在这个和写一个回调函数没有什么区别;那么,如果有多层回调该怎么办?如果callback也是一个异步操作,而且执行完后也需要有相应的回调函数,该怎么办呢?总不能再定义一个callback2,然后给callback传进去吧。而Promise的优势在于,可以在then方法中继续写Promise对象并返回,然后继续调用then来进行回调操作。

    所以:精髓在于:Promise只是能够简化层层回调的写法,而实质上,Promise的精髓是“状态”,用维护状态、传递状态的方式来使得回调函数能够及时调用,它比传递callback函数要简单、灵活的多。所以使用Promise的正确场景是这样的:

    promiseClick()
    .then(function(data){
        console.log(data);
        return runAsync2();
    })
    .then(function(data){
        console.log(data);
        return runAsync3();
    })
    .then(function(data){
        console.log(data);
    });

    这样能够按顺序,每隔两秒输出每个异步回调中的内容,在runAsync2中传给resolve的数据,能在接下来的then方法中拿到。

    (Ps:此处执行多次是因为研究该用法的时候我在一个react的demo中进行的,该页面多个元素改变导致页面多次渲染执行所致,正常页面只渲染一次的话就所有只会执行一次)

    reject的用法

    以上是对promise的resolve用法进行了解释,相当于resolve是对promise成功时候的回调,它把promise的状态修改为

    fullfiled,那么,reject就是失败的时候的回调,他把promise的状态修改为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调。

    function promiseClick(){
    		let p = new Promise(function(resolve, reject){
    			setTimeout(function(){
    				var num = Math.ceil(Math.random()*20); //生成1-10的随机数
    				console.log('随机数生成的值:',num)
    				if(num<=10){
    					resolve(num);
    				}
    				else{
    					reject('数字太于10了即将执行失败回调');
    				}
    			}, 2000);
    		   })
    		   return p
    	   }
    
    	promiseClick().then(
    		function(data){
    			console.log('resolved成功回调');
    			console.log('成功回调接受的值:',data);
    		}, 
    		function(reason){
    			console.log('rejected失败回调');
    			console.log('失败执行回调抛出失败原因:',reason);
    		}
    	);	

    执行结果:

    (PS:此处也是执行多次所以输出多次,执行多次的原因和上次原因一致)

    以上代码:调用promiseClick方法执行,2秒后获取到一个随机数,如果小于10,我们算成功,调用resolve修改Promise的状态为fullfiled。否则我们认为是“失败”了,调用reject并传递一个参数,作为失败的原因。并将状态改成rejected

    运行promiseClick并且在then中传了两个参数,这两个参数分别是两个函数,then方法可以接受两个参数,第一个对应resolve的回调,第二个对应reject的回调。(也就是说then方法中接受两个回调,一个成功的回调函数,一个失败的回调函数,并且能在回调函数中拿到成功的数据和失败的原因),所以我们能够分别拿到成功和失败传过来的数据就有以上的运行结果

    catch的用法

    与Promise对象方法then方法并行的一个方法就是catch,与try  catch类似,catch就是用来捕获异常的,也就是和then方法中接受的第二参数rejected的回调是一样的,如下:

    function promiseClick(){
    		let p = new Promise(function(resolve, reject){
    			setTimeout(function(){
    				var num = Math.ceil(Math.random()*20); //生成1-10的随机数
    				console.log('随机数生成的值:',num)
    				if(num<=10){
    					resolve(num);
    				}
    				else{
    					reject('数字太于10了即将执行失败回调');
    				}
    			}, 2000);
    		   })
    		   return p
    	   }
    
    	promiseClick().then(
    		function(data){
    			console.log('resolved成功回调');
    			console.log('成功回调接受的值:',data);
    		}
    	)
    	.catch(function(reason, data){
    		console.log('catch到rejected失败回调');
    		console.log('catch失败执行回调抛出失败原因:',reason);
    	});	

    执行结果:

    效果和写在then的第二个参数里面一样。它将大于10的情况下的失败回调的原因输出,但是,它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。如下:

    function promiseClick(){
    		let p = new Promise(function(resolve, reject){
    			setTimeout(function(){
    				var num = Math.ceil(Math.random()*20); //生成1-10的随机数
    				console.log('随机数生成的值:',num)
    				if(num<=10){
    					resolve(num);
    				}
    				else{
    					reject('数字太于10了即将执行失败回调');
    				}
    			}, 2000);
    		   })
    		   return p
    	   }
    
    	promiseClick().then(
    		function(data){
    			console.log('resolved成功回调');
    			console.log('成功回调接受的值:',data);
    			console.log(noData);
    		}
    	)
    	.catch(function(reason, data){
    		console.log('catch到rejected失败回调');
    		console.log('catch失败执行回调抛出失败原因:',reason);
    	});	

    执行结果:

    在resolve的回调中,我们console.log(noData);而noData这个变量是没有被定义的。如果我们不用Promise,代码运行到这里就直接在控制台报错了,不往下运行了。但是在这里,会得到上图的结果,也就是说进到catch方法里面去了,而且把错误原因传到了reason参数中。即便是有错误的代码也不会报错了

    all的用法

    与then同级的另一个方法,all方法,该方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后并且执行结果都是成功的时候才执行回调。

    将上述方法复制两份并重命名promiseClick3(), promiseClick2(), promiseClick1(),如下

    function promiseClick1(){
    		let p = new Promise(function(resolve, reject){
    			setTimeout(function(){
    				var num = Math.ceil(Math.random()*20); //生成1-10的随机数
    				console.log('随机数生成的值:',num)
    				if(num<=10){
    					resolve(num);
    				}
    				else{
    					reject('数字太于10了即将执行失败回调');
    				}
    			}, 2000);
    		   })
    		   return p
    	   }
    	   function promiseClick2(){
    		let p = new Promise(function(resolve, reject){
    			setTimeout(function(){
    				var num = Math.ceil(Math.random()*20); //生成1-10的随机数
    				console.log('随机数生成的值:',num)
    				if(num<=10){
    					resolve(num);
    				}
    				else{
    					reject('数字太于10了即将执行失败回调');
    				}
    			}, 2000);
    		   })
    		   return p
    	   }
    	   function promiseClick3(){
    		let p = new Promise(function(resolve, reject){
    			setTimeout(function(){
    				var num = Math.ceil(Math.random()*20); //生成1-10的随机数
    				console.log('随机数生成的值:',num)
    				if(num<=10){
    					resolve(num);
    				}
    				else{
    					reject('数字太于10了即将执行失败回调');
    				}
    			}, 2000);
    		   })
    		   return p
    	   }
    
    	Promise
    		.all([promiseClick3(), promiseClick2(), promiseClick1()])
    		.then(function(results){
    			console.log(results);
    		});

    Promise.all来执行,all接收一个数组参数,这组参数为需要执行异步操作的所有方法,里面的值最终都算返回Promise对象。这样,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面。那么,三个异步操作返回的数据哪里去了呢?都在then里面,all会把所有异步操作的结果放进一个数组中传给then,然后再执行then方法的成功回调将结果接收,结果如下:(分别执行得到结果,all统一执行完三个函数并将值存在一个数组里面返回给then进行回调输出):

    这样以后就可以用all并行执行多个异步操作,并且在一个回调中处理所有的返回数据,比如你需要提前准备好所有数据才渲染页面的时候就可以使用all,执行多个异步操作将所有的数据处理好,再去渲染

    race的用法

    all是等所有的异步操作都执行完了再执行then方法,那么race方法就是相反的,谁先执行完成就先执行回调。先执行完的不管是进行了race的成功回调还是失败回调,其余的将不会再进入race的任何回调

    我们将上面的方法延迟分别改成234秒

    
    function promiseClick1(){
    		let p = new Promise(function(resolve, reject){
    			setTimeout(function(){
    				var num = Math.ceil(Math.random()*20); //生成1-10的随机数
    				console.log('2s随机数生成的值:',num)
    				if(num<=10){
    					resolve(num);
    				}
    				else{
    					reject('2s数字太于10了即将执行失败回调');
    				}
    			}, 2000);
    		   })
    		   return p
    	   }
    	   function promiseClick2(){
    		let p = new Promise(function(resolve, reject){
    			setTimeout(function(){
    				var num = Math.ceil(Math.random()*20); //生成1-10的随机数
    				console.log('3s随机数生成的值:',num)
    				if(num<=10){
    					resolve(num);
    				}
    				else{
    					reject('3s数字太于10了即将执行失败回调');
    				}
    			}, 3000);
    		   })
    		   return p
    	   }
    	   function promiseClick3(){
    		let p = new Promise(function(resolve, reject){
    			setTimeout(function(){
    				var num = Math.ceil(Math.random()*20); //生成1-10的随机数
    				console.log('4s随机数生成的值:',num)
    				if(num<=10){
    					resolve(num);
    				}
    				else{
    					reject('4s数字太于10了即将执行失败回调');
    				}
    			}, 4000);
    		   })
    		   return p
    	   }
     
    	Promise
    		.race([promiseClick3(), promiseClick2(), promiseClick1()])
    		.then(function(results){
    			console.log('成功',results);
    		},function(reason){
    			console.log('失败',reason);
    		});

    当2s后promiseClick1执行完成后就已经进入到了then里面回调,在then里面的回调开始执行时,promiseClick2()和promiseClick3()并没有停止,仍旧再执行。于是再过3秒后,输出了他们各自的值,但是将不会再进入race的任何回调。如图2s生成10进入race的成功回调后,其余函数继续执行,但是将不会再进入race的任何回调,2s生成16进入了race的失败回调,其余的继续执行,但是将不会再进入race的任何回调。

    race的使用比如可以使用在一个请求在10s内请求成功的话就走then方法,如果10s内没有请求成功的话进入reject回调执行另一个操作。

    补充:(由于有人问我怎么实现race的使用比如可以使用在一个请求在10s内请求成功的话就走then方法,如果10s内没有请求成功的话进入reject回调执行另一个操作。这个问题,想是我的表达有点问题,那我就举个例子)

     //请求某个table数据
        function requestTableList(){
            var p = new Promise((resolve, reject) => {
                   //去后台请求数据,这里可以是ajax,可以是axios,可以是fetch 
                    resolve(res);
            });
            return p;
        }
      //延时函数,用于给请求计时 10s
          function timeout(){
              var p = new Promise((resolve, reject) => {
                  setTimeout(() => {
                      reject('请求超时');
                  }, 10000);
              });
              return p;
          }
          Promise.race([requestTableList(), timeout()]).then((data) =>{
            //进行成功回调处理
            console.log(data);
          }).catch((err) => {
            // 失败回调处理
              console.log(err);
          });

    请求一个接口数据,10s内请求完成就展示数据,10s内没有请求完成就提示请求失败

    这里定义了两个promise,一个去请求数据,一个记时10s,把两个promise丢进race里面赛跑去,如果请求数据先跑完就直接进入.then成功回调,将请求回来的数据进行展示;如果计时先跑完,也就是10s了数据请求还没有成功,就先进入race的失败回调,就提示用户数据请求失败进入.catch回调,(ps:或者进入reject的失败回调,当.then里面没有写reject回调的时候失败回调会直接进入.catch)

     

    如果有更精辟的见解欢迎评论留言探讨,一起探讨,一起进步!若回复不及时可联系:

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 75,309
精华内容 30,123
关键字:

promise