欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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對(duì)象異步操作有三種狀態(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對(duì)象的作用:將異步操作以同步操作的流程表達(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 對(duì)象狀態(tài)變 resolved 時(shí)調(diào)用,第二個(gè)回調(diào)函數(shù)是 Promise 對(duì)象的狀態(tài)變?yōu)?rejected 時(shí)調(diào)用。案例如下:

<script>
    // 實(shí)例化 Promise 對(duì)象,接收參數(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 對(duì)象的 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請(qǐng)求

<script>
    const p = new Promise((resolve,reject) =>{
        // 1.創(chuàng)建對(duì)象
        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方法定義在原型對(duì)象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)為成功,返回值為對(duì)象的成功的值
        console.log(value);
        // 1、非promise類型的屬性
        // return 123
        // 2、是promise對(duì)象
        // return new Promise((resolve,reject)=>{
        //     // resolve('ok')
        //     // reject('error')
        // })
        // 3、拋出錯(cuò)誤
        throw new Error('出錯(cuò)啦!!')
    },reason=>{
        console.log(reason);
    })
    // then方法的返回結(jié)果是 Promise 對(duì)象,對(duì)象狀態(tài)由回調(diào)函數(shù)的執(zhí)行結(jié)果決定
    console.log(result);
</script>

then方法返回的是一個(gè)新的Promise實(shí)例,因此可以采用鏈?zhǔn)綄懛?,即then方法后面再調(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對(duì)象實(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對(duì)象 都發(fā)生變化,返回的 Promise 對(duì)象才會(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è)對(duì)象,對(duì)應(yīng)傳入Promise.allSettled()的數(shù)組里面的兩個(gè) Promsie 對(duì)象。

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)有對(duì)象轉(zhuǎn)換為 Promise 對(duì)象。

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

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

相關(guān)文章

  • 在JSP中如何實(shí)現(xiàn)MD5加密的方法

    在JSP中如何實(shí)現(xiàn)MD5加密的方法

    這篇文章主要介紹了在JSP中如何實(shí)現(xiàn)MD5加密的方法,較為詳細(xì)的分析了JSP采用MD5加密的功能、特點(diǎn)及實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下.
    2016-11-11
  • JavaScript實(shí)現(xiàn)數(shù)組在指定位置插入若干元素的方法

    JavaScript實(shí)現(xiàn)數(shù)組在指定位置插入若干元素的方法

    這篇文章主要介紹了JavaScript實(shí)現(xiàn)數(shù)組在指定位置插入若干元素的方法,涉及javascript中splice方法的使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-04-04
  • 淺析Javascript中雙等號(hào)(==)隱性轉(zhuǎn)換機(jī)制

    淺析Javascript中雙等號(hào)(==)隱性轉(zhuǎn)換機(jī)制

    這篇文章給大家詳細(xì)介紹了javascript中雙等號(hào)(==)隱性轉(zhuǎn)換機(jī)制,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧
    2017-10-10
  • js中的閉包學(xué)習(xí)心得

    js中的閉包學(xué)習(xí)心得

    這篇文章主要介紹了js中的閉包學(xué)習(xí)心得以及重要點(diǎn)的代碼寫法,對(duì)此有興趣的朋友跟著小編一起學(xué)習(xí)下吧。
    2018-02-02
  • 5個(gè)書寫JavaScript代碼的壞習(xí)慣,看看你中槍了沒?

    5個(gè)書寫JavaScript代碼的壞習(xí)慣,看看你中槍了沒?

    這篇文章主要介紹了5個(gè)書寫JavaScript代碼的壞習(xí)慣,看看你中槍了沒?,本文指出了你沒有使用命名空間、變量定義的東一個(gè)西一個(gè)、Javascript的變量范圍、Javascript的面向?qū)ο?、new關(guān)鍵字等問題,需要的朋友可以參考下
    2014-11-11
  • 整理JavaScript創(chuàng)建對(duì)象的八種方法

    整理JavaScript創(chuàng)建對(duì)象的八種方法

    JavaScript創(chuàng)建對(duì)象的方法有很多種,本文給大家介紹javascript創(chuàng)建對(duì)象的八種方法,對(duì)javascript創(chuàng)建對(duì)象感興趣的朋友可以參考下本篇文章
    2015-11-11
  • JavaScript this使用方法圖解

    JavaScript this使用方法圖解

    這篇文章主要介紹了JavaScript this使用方法圖解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • 詳解js創(chuàng)建對(duì)象的幾種方法及繼承

    詳解js創(chuàng)建對(duì)象的幾種方法及繼承

    這篇文章主要介紹了js創(chuàng)建對(duì)象的幾種方法及繼承,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • ie6下png圖片背景不透明的解決辦法使用js實(shí)現(xiàn)

    ie6下png圖片背景不透明的解決辦法使用js實(shí)現(xiàn)

    我們時(shí)常在使用png圖片的時(shí)候,在ie6下發(fā)生背景不透明的問題,解決的方法實(shí)在是太多了,下面給大家介紹下一個(gè)js解決的方式,感興趣的朋友可以了解下的
    2013-01-01
  • 微信小程序?qū)崿F(xiàn)折線圖的示例代碼

    微信小程序?qū)崿F(xiàn)折線圖的示例代碼

    這篇文章主要介紹了微信小程序?qū)崿F(xiàn)折線圖的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用小程序具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06

最新評(píng)論