关于javascript:快速入门上手JavaScript中的Promise

3次阅读

共计 5777 个字符,预计需要花费 15 分钟才能阅读完成。

当我还是一个小白的时候,我翻了很多对于 Promise 介绍的文档,我始终没能了解所谓解决异步操作的痛点是什么意思
直到我翻了谷歌第一页的所有中文文档我才有所顿悟,其实从他的英文字面意思了解最为简略粗犷
这就是一个承诺,相当于在代码中提供一个在任何时候承诺之后要做什么事的形式,这个承诺可能会兑现也可能无奈兑现,当然也可能在兑现的过程中
用这个来代替咱们已经须要写的回调函数,能够防止 JavaScript 程序中的回调天堂
所以先不去学习的语法,从另一个形式先了解,心愿能够帮忙你更好的学习或上手Promise

什么是 Promise?

Promise是异步编程的一种解决方案,能够代替传统的解决方案,比方回调函数和事件
其在 ES6 中对立了用法,并提供了原生的 Promise 对象Promise 对象 示意异步操作的最终实现 (或失败) 及其后果值
作为对象,Promise有以下两个特点:

  1. 对象的状态不受外界影响

    • 只有异步操作的后果,能够决定以后是哪一种状态,任何其余操作都无奈扭转这个状态,
      这也是 Promise 这个名字的由来,它的英语意思就是承诺,示意其余伎俩无奈扭转
  2. 一旦状态扭转了就不会在变,也就是说任何时候 Promise 都只有一种状态

    • pending:初始状态,不是胜利或失败状态;
      fulfilled(resolved):操作胜利实现状态;
      rejected:操作失败状态
    • Promise 对象 的状态扭转,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected
      只有这两种状况产生,状态就凝固了,不会再变了,会始终放弃这个后果,
      就算扭转曾经产生了,你再对Promise 对象 增加回调函数,也会立刻失去这个后果,
      这与事件(Event)齐全不同,事件的特点是,如果你错过了它,再去监听,是得不到后果的

Promise 的创立和用处

  1. 构造函数承受一个名为 executor 的函数,此执行函数承受两个 f 函数 参数,resolvereject
new Promise(/* executor */ function(resolve, reject { ...}) );
  1. Promise 通常用于阻塞代码和异步操作,其中包含文件调用,API 调用,DB 调用,IO 调用等等
  2. 这些异步操作的启动产生在执行函数中,如果异步操作胜利,则通过 promise 的创建者调用 resolve() 函数返回预期后果,
    同样,如果出现意外谬误,则通过调用 reject() 函数传递谬误具体信息
  3. 因为 promise 会立刻执行,咱们无奈查看 promise 的初始状态,所以创立一个须要工夫执行的 promise 最简略的形式就是
    应用setTimeOut() 函数,通过浏览器控制台的输入能够直观看到之前所说的状态,以及他的变动过程
    var promiseFir = new Promise(function(resolve, reject) {setTimeout(function() {
            resolve({
                message: '与大家分享常识很开心!',
                code: 200
            });
        }, 2000)
    })
    console.log(promiseFir);
    setTimeout(function() {console.log(promiseFir);
    }, 2000)

Promise 的办法

  1. 3 种原型办法

    • Promise.prototype.then(onFulfilled, onRejected) 链式操作
    • Promise.prototype.catch(onRejected) 捕获谬误
    • Promise.prototype.finally(onFinally) 最终操作
    • 上面用一个小示例简略疾速理解下这三个原型办法的用法
    // 用一个小故事举例,你是一个上学的孩子,你问你的妈妈要一个电话。她说: 这个月底我要买一部手机
    var momsPromise = new Promise(function(resolve, reject) {
        momsSavings = 20000;  // 因为妈妈没有足够储蓄所以无奈买到礼物  
        // momsSavings = 200000;  // 如果妈妈有足够的储蓄就能够买到礼物
        priceOfPhone = 60000;
        if (momsSavings > priceOfPhone) {
            resolve({
                brand: "iphone",
                model: "6s"
            });
        } else {reject("咱们没有足够的储蓄,让咱们多存点钱吧。");
        }
    });
    momsPromise.then(function(value) {console.log("哇,我失去这个电话作为礼物", JSON.stringify(value));
    });
    momsPromise.catch(function(reason) {console.log("妈妈不能给我买电话,因为", reason);
    });
    momsPromise.finally(function() {
        console.log("不论妈妈能不能给我买个电话,我依然爱她");
    });
  1. 4 种静态方法

    • Promise.resolve()
    • Promise.reject()
    • Promise.all()
    • Promise.race()

<span id=”jumpId-then”></span>

Promise.prototype.then(onFulfilled, onRejected) 链式操作

  1. Promise.prototype.then()办法返回的是一个新的Promise 对象,因而能够采纳链式写法
  2. Promise.prototype.then()办法带有以下三个参数:胜利回调,失败回调,后退回调,个别状况下只须要实现第一个,前面是可选的
    function ptFir() {return new Promise(function(resolve, reject) {setTimeout(function() {console.log('办法 1 执行');
                resolve('办法 1 执行结束');
            }, 2000)
        })
    }
    function ptSec() {return new Promise(function(resolve, reject) {setTimeout(function() {console.log('办法 2 执行');
                resolve('办法 2 执行结束');
            }, 1000)
        })
    }
    function ptThi() {return new Promise(function(resolve, reject) {setTimeout(function() {console.log('办法 3 执行');
                resolve('办法 3 执行结束');
            }, 3000)
        })
    }
    ptFir().then(function(data) {console.log('第一个回调:' + data);
        return ptSec();}).then(function(data) {console.log('第二个回调:' + data);
        return ptThi();}).then(function(data) {console.log('第三个回调:' + data);
        return '还没完?该完结了吧!';
    }).then(function(data) {console.log(data);
    })

<span id=”jumpId-catch”></span>

Promise.prototype.catch(onRejected) 捕获谬误

  1. Promise.prototype.catch()办法是 Promise.prototype.then(null, rejection) 的别名,用于指定产生谬误时的回调函数
  2. Promise 对象 的谬误具备 “ 冒泡 ” 性质,会始终向后传递,直到被捕捉为止,也就是说,谬误总是会被下一个 catch 语句捕捉
    promise().then(function(data) {// todo something}).catch(function(err) {// 解决上个回调函数的谬误})

<span id=”jumpId-finally”></span>

Promise.prototype.finally(onFinally) 最终操作

不论 promise 对象 最初的状态,在执行完 .thencatch指定的回调函数当前,都会执行 finally 办法指定的回调函数

    promise().then(function(data) {// todo something}).catch(function(err) {// 解决上个回调函数的谬误}).finally(function(result) {// 解决 then/catch 之后必须执行的操作})

<span id=”jumpId-resolve-reject”></span>

Promise.resolve() / Promise.reject()

  1. 这两个是帮忙办法或快捷方式,它们能够帮忙您轻松创立 resolvereject办法
  2. 须要留神的是:如果 Promise.resolve() 办法的参数,
    不是具备 .then() 办法的对象(又称 thenable 对象),则返回一个新的Promise 对象,且它的状态为fulfilled
    如果Promise.resolve 办法的参数是一个 Promise 对象 的实例,则会被一成不变地返回
  3. Promise.reject()办法同上
    var promise = Promise.resolve('Hello,这里是执行胜利的内容!');
    // var promise = Promise.reject('出错了,这里是被发现的谬误!');  // 胜利和失败只会有一种状态哦  
    promise.then(function(data) {console.log(data)
    });
    promise.catch(function(err) {console.log(err)
    });

<span id=”jumpId-all”></span>

Promise.all()

  1. 当你解决多个 promise 时,最好先创立一个 promise 数组,而后对这些promise 集 执行必要的操作
  2. Promise.all(iterable) 办法 返回一个 Promise 实例,此实例在iterable 参数 内所有的promise
  3. 都实现(resolved)或参数中不蕴含 promise 时回调实现(resolve)
  4. 如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败起因的是第一个 失败 promise的后果
  5. 留神!!!这里的异步操作是并行执行的,等到它们都执行完后才会进到 then() 外面,
    并且 all() 办法会把所有异步操作的后果放进一个数组中传给then()
  6. 上面的示例须要阐明的内容

    • 只有 3 个办法的状态都变成fulfilled,p 的状态才会变成fulfilled,此时 3 个办法的返回值组成一个数组,传递给 p 的回调函数
    • 只有 3 个办法之中有一个被 rejected,p 的状态就变成rejected,此时第一个被reject 的实例的返回值,会传递给 p 的回调函数
    function ptFir() {return new Promise(function(resolve, reject) {setTimeout(function() {console.log('办法 1 执行');
                resolve('办法 1 执行结束');
            }, 2000)
        })
    }
    function ptSec() {return new Promise(function(resolve, reject) {setTimeout(function() {console.log('办法 2 执行');
                resolve('办法 2 执行结束');
            }, 1000)
        })
    }
    function ptThi() {return new Promise(function(resolve, reject) {setTimeout(function() {console.log('办法 3 执行');
                resolve('办法 3 执行结束');
            }, 3000)
        })
    }
    Promise.all([ptFir(), ptSec(), ptThi()]).then(function(data) {console.log(data);
        console.log({}.toString.call(data));
    })

<span id=”jumpId-race”></span>

Promise.race()

  1. Promise.race(iterable)办法返回一个 promise,一旦迭代器中的某个promise 解决或回绝,返回的 promise 就会解决或回绝
  2. all()办法的成果实际上是 「谁跑的慢,以谁为准执行回调」
    那么绝对的就有另一个办法「谁跑的快,以谁为准执行回调」,这就是race() 办法,这个词原本就是赛跑的意思
  3. 这个 race() 办法有什么用呢?应用场景还是很多的,比方咱们能够用 race() 给某个异步申请设置超时工夫,
    并且在超时后执行相应的操作
    // ptFir(), ptSec(), ptThi() 同上
    Promise.all([ptFir(), ptSec(), ptThi()]).then(function(data) {console.log(data);
        console.log({}.toString.call(data));
    })

应用 Promise 的一些教训法令

  1. 进行异步操作或应用阻塞代码时,请应用Promise
  2. 为了代码的可读性,resolve()办法看待 .then(), reject() 办法对应.catch()
  3. 确保同时写入 .catch().then()办法来实现所有的promise
  4. 如果在这两种状况下都须要做一些事件,请应用.finally()
  5. 咱们只有一次扭转每个promise (繁多准则)
  6. 咱们能够在一个 promise 中增加多个处理程序
  7. Promise 对象 中所有办法的返回类型,无论是静态方法还是原型办法,都是Promise
  8. all() 办法中,无论哪个 promise 首先未实现,promise的程序都放弃在值变量中

参考文档一 ———— 彻底了解 Javascript 中的 Promise
参考文档二 ———— 艰深通俗的了解 Promise 中的 then
参考文档三 ———— 了解 Javascript 中的 Promise
参考文档四 ———— JavaScript Promise 对象

正文完
 0