最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript中的Promise詳解

 更新時(shí)間:2022年11月08日 11:32:28   作者:亦世凡華、  
現(xiàn)在網(wǎng)上有非常多的Promise文章,但都是給你一堆代碼,或者某些核心代碼,讓你看完之后感覺,嗯,很厲害,但還是不知所云,不知其所以然。那么本文真正從一個(gè)小白開始帶你深入淺出,一步一步實(shí)現(xiàn)自己的 Promise,這種自己造輪子的過程一定是進(jìn)步最快的過程,快上車開始吧

前言

Promise是ES6引入的異步編程的新解決方案。語法上Promise是一個(gè)構(gòu)造函數(shù),用來封裝異步操作并可以獲取其成功或失敗的結(jié)果。

Promise特點(diǎn):

Promsie對象異步操作有三種狀態(tài),pending(進(jìn)行中)、fulfilled(已成功)和reject(已失敗)。只有異步操作才可以決定當(dāng)前是哪種狀態(tài);Promise狀態(tài)改變有兩種可能,從pending變?yōu)閒ulfidded和從pending變?yōu)閞ejected。狀態(tài)發(fā)生改變就不能再改變了,稱為:resolved(已定型)

Promise對象的作用:將異步操作以同步操作的流程表達(dá)出來,避免層層嵌套的回調(diào)函數(shù),而且Promise提供了統(tǒng)一的接口,使得控制異步操作更加容易。

Promise使用

Promise構(gòu)造函數(shù)接收一個(gè)函數(shù)作為參數(shù),該函數(shù)的兩個(gè)參數(shù)分別為:resolve 和 reject。

resolve:在異步操作成功時(shí)調(diào)用,并將異步操作的結(jié)果作為參數(shù)傳遞出去。

reject:在異步操作失敗時(shí)調(diào)用,并將異步操作報(bào)出的錯(cuò)誤作為參數(shù)傳遞出去。

Promise實(shí)例生成后,可以用 then 方法分別指定 resolved 狀態(tài)和 rejected 狀態(tài)的回調(diào)函數(shù);而第一個(gè)回調(diào)函數(shù)是 Promise 對象狀態(tài)變 resolved 時(shí)調(diào)用,第二個(gè)回調(diào)函數(shù)是 Promise 對象的狀態(tài)變?yōu)?rejected 時(shí)調(diào)用。案例如下:

<script>
    // 實(shí)例化 Promise 對象,接收參數(shù)為函數(shù)類型值
    const p = new Promise(function(resolve,reject){
        // 封裝異步操作
        setTimeout(function(){
            // 數(shù)據(jù)操作
            // let data = '用戶數(shù)據(jù)'
            // resolve
            // resolve(data)
            let err = '數(shù)據(jù)讀取失敗'
            reject(err)
        },1000)
    })
    // 調(diào)用 Promise 對象的 then 方法
    // 數(shù)據(jù)調(diào)用成功,則調(diào)用下面第一個(gè)回調(diào),失敗則是第二個(gè)
    p.then(function(value){//成功的形參
        console.log(value);
    },function(reason){//失敗的形參
        console.log(reason);
    })
</script>

Promise新建后會(huì)立即執(zhí)行,然而 then 方法指定的回調(diào)函數(shù)將在當(dāng)前腳本所有同步任務(wù)執(zhí)行完才會(huì)執(zhí)行。

<script>
    let p = new Promise(function(resolve,reject){
        console.log('People');
        // 數(shù)據(jù)操作
        let data = 'World'
        resolve(data)
    })
    p.then(function(value){
        console.log(value);
    })
    console.log('Hello');
</script>

Promise封裝Ajax請求

<script>
    const p = new Promise((resolve,reject) =>{
        // 1.創(chuàng)建對象
        const xhr = new XMLHttpRequest()
        // 2.初始化
        xhr.open("GET","https://ai.baidu.com/")
        // 3.發(fā)送
        xhr.send()
        // 4.綁定事件,處理響應(yīng)結(jié)果
        xhr.onreadystatechange = function(){
            // 判斷
            if(xhr.readyState ===4 ){
                // 判斷響應(yīng)碼 200-299
                if(xhr.status >= 200 && xhr.status <300){
                    // 表示成功
                    resolve(xhr.response);
                }else{
                    // 如果失敗
                    reject(xhr.status);
                }
            }
        }
    })
    // 指定成功和失敗的回調(diào)
    p.then(function(value){
        console.log(value);
    },function(reason){
        console.error(reason);
    })
</script>

Promise封裝讀取文件

這里借助 Node.js 方法進(jìn)行讀取文件,不了解Node.js的方法可以關(guān)注我,后期會(huì)出相關(guān)專欄。

// 1.引入 fs 模塊
const fs = require('fs')
// 2.調(diào)用方法讀取文件
// fs.readFile('./index.md',(err,data)=>{
//     // 如果失敗,則拋出錯(cuò)誤
//     if(err) throw err;
//     // 如果沒有出錯(cuò),則輸出內(nèi)容
//     console.log(data.toString());
// })
// 3.使用 Promise 封裝
const p = new Promise(function(resolve,reject){
    fs.readFile('./index.md',(err,data)=>{
        // 判斷如果失敗
        if(err) reject(err)
        // 如果成功
        resolve(data)
    })
})
p.then(function(value){
    console.log(value.toString());
},function(reason){
    console.log("讀取失敗!!");
})

Promise.prototype.then方法

Promise實(shí)例具有then方法,即then方法定義在原型對象Promise.prototype上,作用是為Promise實(shí)例添加狀態(tài)改變時(shí)的回調(diào)函數(shù)。案例如下:

<script>
    // 創(chuàng)建 promise 兌現(xiàn)
    const p = new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve('用戶數(shù)據(jù)')
            // reject('出錯(cuò)啦')
        })
    })
    // 調(diào)用 then 方法 
    const result = p.then(value =>{
        // 如果回調(diào)函數(shù)中返回的結(jié)果是非 promise 類型屬性,狀態(tài)為成功,返回值為對象的成功的值
        console.log(value);
        // 1、非promise類型的屬性
        // return 123
        // 2、是promise對象
        // return new Promise((resolve,reject)=>{
        //     // resolve('ok')
        //     // reject('error')
        // })
        // 3、拋出錯(cuò)誤
        throw new Error('出錯(cuò)啦??!')
    },reason=>{
        console.log(reason);
    })
    // then方法的返回結(jié)果是 Promise 對象,對象狀態(tài)由回調(diào)函數(shù)的執(zhí)行結(jié)果決定
    console.log(result);
</script>

then方法返回的是一個(gè)新的Promise實(shí)例,因此可以采用鏈?zhǔn)綄懛ǎ磘hen方法后面再調(diào)用另一個(gè)then方法。但是前一個(gè)then()方法中的回調(diào)函數(shù)中又可能返回一個(gè)Promise實(shí)例,這時(shí)候后面一個(gè)then()方法中的回調(diào)函數(shù)會(huì)等前一個(gè)Promise實(shí)例狀態(tài)發(fā)生變化才會(huì)調(diào)用。案例如下:

<script>
    let p = new Promise((resolve, reject) => {
        setTimeout(()=>{
            resolve('success')
        });
    },1000);
    p.then(
        res => {
            console.log(res);
            return `${res} again`;
        }
        )
        .then(
            res => console.log(res)
    );
</script>

Promise多文件讀取

回調(diào)地獄與Promise對象實(shí)現(xiàn)相比,不會(huì)產(chǎn)生回調(diào)現(xiàn)象,而且也不用再數(shù)據(jù)龐大時(shí)進(jìn)行大規(guī)模的縮進(jìn)。承接上文單文件讀取,現(xiàn)在進(jìn)行多文件讀取,案例如下:

// 1.引入 fs 模塊
const { rejects } = require('assert')
const fs = require('fs')
const { resolve } = require('path')
// 2.回調(diào)地獄 調(diào)用方法讀取文件
// fs.readFile('./index.md',(err,data)=>{
//     fs.readFile('./index1.md',(err,data1)=>{
//         fs.readFile('./index2.md',(err,data2)=>{
//             let result = data + '\r\n' + data1 +'\r\n'+ data2
//             console.log(result);
//         })
//     })
// })
// 3.使用 Promise 實(shí)現(xiàn)
const p = new Promise((resolve,reject)=>{
    fs.readFile('./index.md',(err,data)=>{
        resolve(data)
    })
})
// value 是第一個(gè)文件的內(nèi)容
p.then(value => {
    return new Promise((resolve,reject)=>{
        fs.readFile('./index1.md',(err,data)=>{//data是第二個(gè)文件的內(nèi)容
            // 返回的是第一個(gè)和第二個(gè)文件合并的數(shù)組
            resolve([value, data])
        })
    })
}).then(value => {//這里的value就是上面合并的數(shù)組
    return new Promise((resolve,reject)=>{
        fs.readFile('./index2.md',(err,data)=>{//data是第三個(gè)文件的內(nèi)容
            // 壓入
            value.push(data)
            resolve(value)
        })
    })
}).then(value => {//如果上面成功,現(xiàn)在的value就是返回三個(gè)數(shù)組的合集
    console.log(value.join('\r\n'));//數(shù)組用join進(jìn)行拼接
})

Promise.prototype.catch()

該方法用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。舉個(gè)簡單的例子:

<script>
    const p = new Promise((resolve,reject)=>{
        setTimeout(function(){
            reject('出錯(cuò)了!')
        },1000)
    })
    // p.then(value=>{},reason=>{
    //     console.log(reason);
    // })
    p.catch(reason=>{
        console.log(reason);
    })
</script>

Promise.prototype.finally()

finally()方法指定不管promise最后的狀態(tài)如何,在執(zhí)行完then或catch指定的回調(diào)函數(shù)以后,都會(huì)執(zhí)行finally方法指定的回調(diào)函數(shù)。

<script>
    const p = new Promise((resolve,reject)=>{
        setTimeout(function(){
            reject('出錯(cuò)了!')
        },1000)
    })
    p.catch(reason=>{
        console.log(reason);
    }).finally(()=>{
        console.log('我是finall,不管promise結(jié)果如何我都要執(zhí)行');
    })
</script>

Promise.all()

該方法用于將多個(gè) Promise 實(shí)例包裝成一個(gè)新的 Promise 實(shí)例,方法接受一個(gè)數(shù)組作為參數(shù),數(shù)組參數(shù)都是Promsie實(shí)例。當(dāng)然參數(shù)也可以不是數(shù)組,但必須有Iterator接口,且返回的每個(gè)成員都是Promise實(shí)例。

該方法只適合所有異步都操作成功的情況,如果有一個(gè)操作失敗就無法滿足要求。

<script>
    // Promise.all()的狀態(tài)由參數(shù)決定:分以下兩種情況
    /* 
    * (1)Promise.all()參數(shù)的狀態(tài)都變成fulfilled,Promise.all()狀態(tài)才會(huì)變成fulfilled,此時(shí)所有參數(shù)的返回值組成一個(gè)數(shù)組,傳遞給Promise.all()的回調(diào)函數(shù)。
    * (2)只要參數(shù)之中有一個(gè)被rejected,Promise.all()的狀態(tài)就變成rejected,此時(shí)第一個(gè)被reject的實(shí)例的返回值,會(huì)傳遞給p的回調(diào)函數(shù)。
    */
    const p1 = new Promise((resolve, reject) => {
        resolve('hello');
    })
    .then(result => result);
    const p2 = new Promise((resolve, reject) => {
        throw new Error('報(bào)錯(cuò)了');
    })
    .then(result => result);
    Promise.all([p1, p2])
    .then(result => console.log(result))
    .catch(e => console.log(e));//Error:報(bào)錯(cuò)了
</script>

Promise.race()

該方法同樣是將多個(gè) Promise 實(shí)例包裝成一個(gè)新的 Promsie 實(shí)例,該方法與 Promise.all()方法一樣,區(qū)別是該方法中只要參數(shù)之中有一個(gè)實(shí)例率先改變狀態(tài),該方法的實(shí)例狀態(tài)跟著改變,那個(gè)率先改變的 Promise 實(shí)例的返回值就傳遞給該方法實(shí)例的回調(diào)函數(shù)。

<script>
    const p = Promise.race([
        fetch('./index.js'),
        new Promise(function (resolve, reject) {
        setTimeout(() => reject(new Error('request timeout')), 5000)
        })
    ]);
    p.then(console.log).catch(console.error);
</script>

上面代碼中,如果 5 秒之內(nèi)fetch方法無法返回結(jié)果,變量p的狀態(tài)就會(huì)變成rejected,從而觸發(fā)catch方法指定的回調(diào)函數(shù)。

Promise.allSettled()

該方法用來確定一組異步是否都結(jié)束(不管成功或失敗)。方法接受一個(gè)數(shù)組作為參數(shù),只有當(dāng)參數(shù)數(shù)組中所有 Promise對象 都發(fā)生變化,返回的 Promise 對象才會(huì)發(fā)生狀態(tài)變更。

<script>
    const resolved = Promise.resolve(42);
    const rejected = Promise.reject(-1);
    const allSettledPromise = Promise.allSettled([resolved, rejected]);
    allSettledPromise.then(function (results) {
        console.log(results);
    });
</script>

回調(diào)函數(shù)接受到的參數(shù)是數(shù)組results,該數(shù)組的每一個(gè)成員都是一個(gè)對象,對應(yīng)傳入Promise.allSettled()的數(shù)組里面的兩個(gè) Promsie 對象。

Pomise.any()

Promise.any()和Promise.race()方法很像,唯一區(qū)別就是Promise.any()不會(huì)因?yàn)槟硞€(gè) Promise 變成 rejected 狀態(tài)而結(jié)束,必須等到所有參數(shù) Promise 變成 rejected 狀態(tài)才會(huì)結(jié)束。

var resolved = Promise.resolve(42);
var rejected = Promise.reject(-1);
var alsoRejected = Promise.reject(Infinity);
Promise.any([resolved, rejected, alsoRejected]).then(function (result) {
  console.log(result); // 42
});
Promise.any([rejected, alsoRejected]).catch(function (results) {
  console.log(results instanceof AggregateError); // true
  console.log(results.errors); // [-1, Infinity]
});

Promise.resolve()

該方法能夠?qū)F(xiàn)有對象轉(zhuǎn)換為 Promise 對象。

Promise.resolve('foo')
// 等價(jià)于
new Promise(resolve => resolve('foo'))

到此這篇關(guān)于JavaScript中的Promise詳解 的文章就介紹到這了,更多相關(guān)JS Promise內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JS調(diào)用Android、Ios原生控件

    JS調(diào)用Android、Ios原生控件

    本文主要介紹了JS調(diào)用Android、Ios通信的相同點(diǎn)和不同點(diǎn),以便幫助我們在進(jìn)行混合式開發(fā)時(shí),提高代碼質(zhì)量,實(shí)現(xiàn)兩者在網(wǎng)頁端代碼的統(tǒng)一。下面跟著小編一起來看下吧
    2017-01-01
  • js實(shí)現(xiàn)功能比較全面的全選和多選

    js實(shí)現(xiàn)功能比較全面的全選和多選

    本文主要分享了js實(shí)現(xiàn)功能比較全面的全選和多選的示例代碼,具有很好的參考價(jià)值。下面跟著小編一起來看下吧
    2017-03-03
  • fetch 如何實(shí)現(xiàn)請求數(shù)據(jù)

    fetch 如何實(shí)現(xiàn)請求數(shù)據(jù)

    這篇文章主要介紹了fetch 如何實(shí)現(xiàn)請求數(shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • momentjs使用詳細(xì)說明

    momentjs使用詳細(xì)說明

    這篇文章主要介紹了momentjs詳細(xì)使用說明,使用 Moment.js 可以輕松地獲取上周、上月和前三個(gè)月的起始和結(jié)束時(shí)間,在示例中,我們傳入了 '2023-07-15',并將返回的日期信息存儲(chǔ)在 dateInfo 變量中,然后將其打印到控制臺(tái)上,需要的朋友可以參考下
    2023-07-07
  • JS獲取CSS樣式(style/getComputedStyle/currentStyle)

    JS獲取CSS樣式(style/getComputedStyle/currentStyle)

    這篇文章主要為大家介紹了JS獲取CSS樣式的方法,介紹了CSS樣式的三種分類情況,對獲取樣式做一個(gè)簡單的封裝,感興趣的小伙伴們可以參考一下
    2016-01-01
  • 詳解JavaScript中的坐標(biāo)和距離

    詳解JavaScript中的坐標(biāo)和距離

    在前端開發(fā)中總會(huì)遇到各種各樣需要使用或計(jì)算坐標(biāo)和距離的情況,于是便有了整理記錄的想法,即加深了印象,又方便隨時(shí)查閱。
    2019-05-05
  • js實(shí)現(xiàn)非常簡單的焦點(diǎn)圖切換特效實(shí)例

    js實(shí)現(xiàn)非常簡單的焦點(diǎn)圖切換特效實(shí)例

    這篇文章主要介紹了js實(shí)現(xiàn)非常簡單的焦點(diǎn)圖切換特效,是一個(gè)非常簡單的js焦點(diǎn)圖切換效果,涉及javascript操作鼠標(biāo)事件與圖片的相關(guān)技巧,需要的朋友可以參考下
    2015-05-05
  • js操作table示例(個(gè)人心得)

    js操作table示例(個(gè)人心得)

    有一個(gè)表格,然后有4個(gè)輸入框,一個(gè)合并按鈕,輸入框是這樣的,從第幾行到第幾行,從第幾列到第幾列,然后點(diǎn)擊按鈕,合并
    2013-11-11
  • Bootstrap實(shí)現(xiàn)前端登錄頁面帶驗(yàn)證碼功能完整示例

    Bootstrap實(shí)現(xiàn)前端登錄頁面帶驗(yàn)證碼功能完整示例

    這篇文章主要介紹了Bootstrap實(shí)現(xiàn)前端登錄頁面帶驗(yàn)證碼功能,結(jié)合完整實(shí)例形式分析了Bootstrap前端登錄頁面帶驗(yàn)證碼界面布局與功能實(shí)現(xiàn)相關(guān)操作技巧,需要的朋友可以參考下
    2020-03-03
  • JS實(shí)現(xiàn)倒計(jì)時(shí)(天數(shù)、時(shí)、分、秒)

    JS實(shí)現(xiàn)倒計(jì)時(shí)(天數(shù)、時(shí)、分、秒)

    這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)倒計(jì)時(shí),精確到天數(shù)、時(shí)、分、秒,還為大家分享了parseInt() 函數(shù)的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11

最新評論

文安县| 日土县| 泾川县| 无锡市| 措美县| 榆林市| 灵宝市| 二连浩特市| 南阳市| 榆中县| 阳朔县| 根河市| 大同县| 临沂市| 吉木乃县| 镇雄县| 孝义市| 景德镇市| 化隆| 光泽县| 襄城县| 仪征市| 新田县| 饶阳县| 兰州市| 盐边县| 广南县| 平原县| 富锦市| 岢岚县| 商水县| 司法| 克拉玛依市| 梁河县| 洛隆县| 东城区| 章丘市| 文昌市| 涞源县| 大渡口区| 乌兰县|