JS基礎(chǔ):異步編程之Promise罢洲、async-await

目錄

一. Promise
?1. 為什么要使用Promise
?2. Promise是什么
?3. 如何使用Promise
?4.fetch纹份、AsyncStorage使用示例
二. async-await


一. Promise


1. 為什么要使用Promise

關(guān)于事件循環(huán)吕漂、線程、隊(duì)列套耕、同步任務(wù)谁帕、異步任務(wù),這里就不展開(kāi)了冯袍,簡(jiǎn)單說(shuō)下它們?cè)贘S里的情況匈挖。

為了程序執(zhí)行的簡(jiǎn)單,JS被設(shè)計(jì)為單線程的康愤,也就是說(shuō)JS里的所有任務(wù)都是在主線程里執(zhí)行的儡循,下一個(gè)任務(wù)必須得等上一個(gè)任務(wù)執(zhí)行完畢才能執(zhí)行,這也就是同步任務(wù)征冷。但是如果一個(gè)任務(wù)的執(zhí)行時(shí)間可能很長(zhǎng)(如一個(gè)任務(wù)里包含了網(wǎng)絡(luò)請(qǐng)求择膝、數(shù)據(jù)庫(kù)讀寫(xiě)等IO操作),它就會(huì)阻塞主線程检激,導(dǎo)致后面的任務(wù)也無(wú)法執(zhí)行肴捉,不過(guò)讓后面的任務(wù)等也不是不行,如果是因?yàn)槟硞€(gè)任務(wù)計(jì)算量大而導(dǎo)致CPU忙不過(guò)來(lái)叔收,那這個(gè)等就是不可避免的每庆,也是有效的,但很多情況的等卻是任務(wù)中IO操作的部分出結(jié)果很慢今穿,導(dǎo)致我們一直拿不到結(jié)果,CPU就只能在那閑著干等伦籍,等到結(jié)果后再繼續(xù)執(zhí)行該任務(wù)蓝晒。于是JS的設(shè)計(jì)者就設(shè)計(jì)腮出,CPU完全可以不管某個(gè)任務(wù)中IO操作的部分,當(dāng)某個(gè)任務(wù)執(zhí)行IO操作的時(shí)候芝薇,就掛起這個(gè)任務(wù)胚嘲,并把這個(gè)任務(wù)放到一個(gè)專(zhuān)門(mén)的隊(duì)列中去,讓CPU繼續(xù)執(zhí)行后面的任務(wù)洛二,等IO操作返回了結(jié)果馋劈,再把這個(gè)任務(wù)從隊(duì)列里拿出來(lái)放到主線程中繼續(xù)執(zhí)行下去,于是這種任務(wù)就成了異步任務(wù)晾嘶,它不會(huì)阻塞主線程妓雾,而這種一遍一遍不停地檢查異步任務(wù)是否該繼續(xù)執(zhí)行的機(jī)制就是JS里面的事件循環(huán)機(jī)制(Event Loop)。

一個(gè)異步任務(wù)的通常寫(xiě)法都是:IO操作 + 回調(diào)函數(shù)垒迂。IO操作為一種耗時(shí)操作械姻,回調(diào)函數(shù)用來(lái)指定耗時(shí)操作結(jié)束后接下來(lái)該任務(wù)要干什么。JS里設(shè)計(jì)如果一個(gè)異步任務(wù)沒(méi)有回調(diào)函數(shù)机断,那么它在執(zhí)行IO操作被掛起后楷拳,就不會(huì)把它放入任務(wù)隊(duì)列中,那么當(dāng)IO操作返回結(jié)果后吏奸,它也就不會(huì)再次進(jìn)入主線程繼續(xù)執(zhí)行了欢揖,因?yàn)樗鼪](méi)有用回調(diào)函數(shù)指定下一步要干什么。但如果異步任務(wù)指定了回調(diào)函數(shù)奋蔚,那么當(dāng)異步任務(wù)重新進(jìn)入主線程時(shí)她混,就是執(zhí)行對(duì)應(yīng)的回調(diào)函數(shù)。

下面我們舉例子來(lái)看看異步任務(wù)的編寫(xiě)旺拉。

假定f1要做個(gè)異步任務(wù)产上,f2f1的回調(diào)函數(shù)。

function f1(callback) {
    // f1任務(wù)的耗時(shí)代碼
    
    // f1任務(wù)的耗時(shí)代碼執(zhí)行完后蛾狗,執(zhí)行回調(diào)函數(shù)
    callback();
}

f1(f2);

使用回調(diào)函數(shù)法來(lái)實(shí)現(xiàn)異步任務(wù)的優(yōu)點(diǎn)是簡(jiǎn)單和容易理解晋涣,但是卻可能出現(xiàn)下面這樣的使用情況。

function async(arg, callback) {
    console.log('參數(shù)為 ' + arg +' , 1秒后返回結(jié)果');
    setTimeout(function () { callback(arg * 2); }, 1000);
}

function final(value) {
    console.log('完成: ', value);
}

async(1, function (value) {
    async(2, function (value) {
        async(3, function (value) {
            async(4, function (value) {
                async(5, function (value) {
                    async(6, final);
                });
            });
        });
    });
});


// 參數(shù)為 1 , 1秒后返回結(jié)果
// 參數(shù)為 2 , 1秒后返回結(jié)果
// 參數(shù)為 3 , 1秒后返回結(jié)果
// 參數(shù)為 4 , 1秒后返回結(jié)果
// 參數(shù)為 5 , 1秒后返回結(jié)果
// 參數(shù)為 6 , 1秒后返回結(jié)果
// 完成:  12

如果像上面這樣沉桌,異步任務(wù)的回調(diào)函數(shù)又是一個(gè)異步任務(wù)谢鹊,那回調(diào)函數(shù)就會(huì)一直嵌套下去,此時(shí)代碼的結(jié)構(gòu)就有點(diǎn)亂了留凭,我們也無(wú)法從代碼中清晰地閱讀出每個(gè)異步任務(wù)的耗時(shí)任務(wù)完成后佃扼,接下來(lái)要做什么。

Promise的出現(xiàn)蔼夜,就是為了解決異步任務(wù)的回調(diào)函數(shù)可能過(guò)于臃腫和不易閱讀的問(wèn)題兼耀,下面我們來(lái)詳細(xì)看看它。

2. Promise是什么

Promise的主要用途就是通過(guò)thencatch等方法來(lái)給異步任務(wù)設(shè)置回調(diào)瘤运,代替掉原來(lái)回調(diào)函數(shù)的那種實(shí)現(xiàn)方案窍霞,從而使得整個(gè)異步任務(wù)的流程更清晰,代碼更易讀拯坟。例如上面的例子但金,使用Promise后如下。

(new Promise(stpe1))
    .then(step2)
    .then(step3)
    .then(step4);

Promise是一個(gè)對(duì)象郁季,也是一個(gè)構(gòu)造函數(shù)冷溃。Promise構(gòu)造函數(shù)接受一個(gè)函數(shù)f1作為參數(shù),f1里面是異步任務(wù)的代碼梦裂,返回的p1就是一個(gè)Promise對(duì)象似枕。下面一小節(jié)我們會(huì)做詳細(xì)的介紹。

var p1 = new Promise(f1);

Promise對(duì)象有三種狀態(tài)塞琼。

  • 異步操作進(jìn)行中(pending
  • 異步操作成功(fulfilled
  • 異步操作失敳ぞ弧(rejected

這三種狀態(tài)之間的轉(zhuǎn)變只有兩種可能,而且一旦狀態(tài)發(fā)生變化彪杉,就凝固了毅往,不會(huì)再發(fā)生變化。

  • 異步操作進(jìn)行中 ——> 異步操作成功
  • 異步操作進(jìn)行中 ——> 異步操作失敗

因此派近,Promise對(duì)象的最終狀態(tài)只有兩種攀唯。

  • 異步操作成功
  • 異步操作失敗

注意:

fulfilledrejected兩種狀態(tài)合在一起又可以稱(chēng)為resolved狀態(tài)(已定型),但是為了行文方便渴丸,本篇后面的resolved狀態(tài)統(tǒng)一只指fulfilled狀態(tài)侯嘀,不包含rejected狀態(tài)。

3. 如何使用Promise

  • 第一步:使用Promise構(gòu)造函數(shù)谱轨,通過(guò)固定的格式來(lái)包裹異步任務(wù)戒幔,并將異步任務(wù)的執(zhí)行結(jié)果或錯(cuò)誤傳遞出去

有了Promise之后,如果我們想給某個(gè)異步任務(wù)添加回調(diào)函數(shù)土童,就不是編寫(xiě)一個(gè)普通的函數(shù)诗茎,在內(nèi)部做異步任務(wù)并執(zhí)行回調(diào)函數(shù)了,而是直接使用Promise構(gòu)造函數(shù)献汗,通過(guò)固定的格式來(lái)包裹異步任務(wù)敢订,并將異步任務(wù)的執(zhí)行結(jié)果或錯(cuò)誤傳遞出去。

const promise = new Promise(function (resolve, reject) {
    // some code...

    if (/* 異步任務(wù)執(zhí)行成功 */){
        resolve(value);
    } else { /* 異步任務(wù)執(zhí)行失敗 */
        reject(error);
    }
});

上面代碼中罢吃,Promise構(gòu)造函數(shù)接收一個(gè)函數(shù)作為參數(shù)楚午。該參數(shù)函數(shù)的兩個(gè)參數(shù)分別是而且必須是resolvereject,它們倆是JS提供的系統(tǒng)函數(shù)尿招,不需要我們自己部署矾柜,我們只要這么固定地寫(xiě)就可以了阱驾;該參數(shù)函數(shù)的執(zhí)行體就是要執(zhí)行的異步任務(wù),并通過(guò)resolve(value)reject(error)固定的寫(xiě)法怪蔑,將異步任務(wù)的執(zhí)行結(jié)果或錯(cuò)誤傳遞出去啊易,執(zhí)行體會(huì)在Promise對(duì)象創(chuàng)建之后立即執(zhí)行。

通過(guò)以上的固定寫(xiě)法饮睬,我們知道resolve函數(shù)會(huì)在異步操作成功時(shí)觸發(fā),并將異步操作的結(jié)果作為參數(shù)傳遞出去篮奄,這個(gè)函數(shù)的執(zhí)行會(huì)把Promise對(duì)象的狀態(tài)從pending變?yōu)?code>resolved捆愁;reject函數(shù)會(huì)在在異步操作失敗時(shí)觸發(fā),并將異步操作的錯(cuò)誤作為參數(shù)傳遞出去窟却,這個(gè)函數(shù)的執(zhí)行會(huì)把Promise對(duì)象的狀態(tài)從pending變?yōu)?code>rejected昼丑。

  • 第二步:使用Promise的then方法和catch方法,為異步任務(wù)添加回調(diào)函數(shù)

在第一步中夸赫,我們并沒(méi)有直接為異步任務(wù)添加回調(diào)函數(shù)菩帝,而僅僅是通過(guò)resolve(value)reject(error)把異步任務(wù)的結(jié)果或錯(cuò)誤傳遞出來(lái)了,現(xiàn)在我們來(lái)為異步任務(wù)添加回調(diào)函數(shù)茬腿。

Promise對(duì)象生成之后呼奢,我們可以通過(guò)它的then方法,分別指定它變?yōu)?code>resolved狀態(tài)(即異步任務(wù)執(zhí)行成功)和rejected狀態(tài)(即異步任務(wù)執(zhí)行失斍衅健)后的回調(diào)函數(shù)握础。

promise.then(function (value) {
    // success
}, function (error) {
    // failure
});

then方法可以接受兩個(gè)回調(diào)函數(shù)作為參數(shù)。第一個(gè)回調(diào)函數(shù)會(huì)在異步任務(wù)執(zhí)行成功調(diào)用悴品,第一步傳出來(lái)的value就能在這里接收到禀综;第二個(gè)回調(diào)函數(shù)會(huì)在異步任務(wù)執(zhí)行失敗調(diào)用,第一步時(shí)傳出來(lái)的error就能在這里接收到苔严。其中第二個(gè)函數(shù)是可選的定枷,不一定要提供。

同時(shí)then方法執(zhí)行后的返回值又是一個(gè)新的Promise對(duì)象(注意不是原來(lái)那個(gè)Promise對(duì)象了)届氢,因此可以對(duì)then方法采用鏈?zhǔn)綄?xiě)法欠窒,這時(shí)上一個(gè)then方法參數(shù)函數(shù)的執(zhí)行結(jié)果,會(huì)自動(dòng)傳遞給下一個(gè)then方法的參數(shù)函數(shù)作為參數(shù)悼沈。

promise.then(function (異步任務(wù)的執(zhí)行結(jié)果) {
    // ...
    return 結(jié)果1;
}).then(function (結(jié)果1) {
    // ...
    return 結(jié)果2;
}).then(function (結(jié)果2) {
    // ...
});

除了then方法之外贱迟,Promise還有一個(gè)catch方法,它其實(shí)是.then(null, rejection).then(undefined, rejection)的別名絮供,可以專(zhuān)門(mén)用來(lái)指定Promise對(duì)象變?yōu)?code>rejected狀態(tài)(即異步任務(wù)執(zhí)行失斠路汀)的回調(diào)函數(shù)。

promise.then(function () {
    // ...
    return 結(jié)果1;
}).then(function (結(jié)果1) {
    // ...
    return 結(jié)果2;
}).then(function (結(jié)果2) {
    // ...
}).catch(function (error) {
    // ...
});

catch方法可以捕捉它上面所有then方法的錯(cuò)誤壤靶,使用catch方法捕捉錯(cuò)誤要比使用then方法既捕捉成功也捕捉的代碼看起來(lái)清晰明了缚俏。因此我們推薦,使用then方法提供異步任務(wù)成功的回調(diào),而使用catch方法提供異步任務(wù)失敗的回調(diào)忧换。

4.fetch恬惯、AsyncStorage使用示例

// ProjectRequest.js

/**
 * RN提供的fetch方法,是異步的亚茬,它本身就會(huì)返回一個(gè)Promise對(duì)象酪耳。因?yàn)檫@里我們對(duì)它進(jìn)行了封裝使用,所以外面又包了一層Promise刹缝,來(lái)給fetch這個(gè)異步任務(wù)提供回調(diào)碗暗,這樣外界才能拿到它的結(jié)果。
 *
 * @param url
 * @param params
 * @returns {Promise<any> | Promise}
 */
static post(url, params) {
    return new Promise((resolve, reject) => {
        fetch(url, {
            method: 'POST',
            headers: {
                Accept: 'application/json',
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(params)
        })
            .then(response => {
                if (response.ok) {
                    // 請(qǐng)求到的response其實(shí)是一個(gè)Response對(duì)象梢夯,它是一個(gè)很原始的數(shù)據(jù)格式言疗,我們不能直接使用,先獲取它的JSON字符串文本格式
                    return response.text();
                } else {
                    throw new Error('網(wǎng)絡(luò)請(qǐng)求失斔淘摇噪奄!');
                }
            })
            .then(responseText => {

                // 然后把JSON字符串序列化為JS對(duì)象
                const responseJSObj = JSON.parse(responseText);

                // 把請(qǐng)求成功的數(shù)據(jù)傳遞出去
                resolve(responseJSObj);
            })
            .catch((error) => {
                // 把請(qǐng)求失敗的信息傳遞出去
                reject(error);
            })
    })
}
// ThemeDao.js

/**
 * 讀取主題色
 * RN提供的AsyncStorage,它的讀取和寫(xiě)入操作都是是異步的人乓,只通過(guò)回調(diào)函數(shù)的方式來(lái)告訴我們結(jié)果勤篮。因?yàn)檫@里我們對(duì)它進(jìn)行了封裝使用,所以外面又包了一層Promise撒蟀,來(lái)給AsyncStorage這個(gè)異步任務(wù)提供回調(diào)叙谨,這樣外界才能拿到它的結(jié)果。
 *
 * @returns {Promise<any> | Promise}
 */
static getThemeColor() {
    return new Promise((resolve, reject) => {
        AsyncStorage.getItem(THEME_COLOR, (error, value) => {
            if (error) {
                reject(error);
            } else {
                if (!value) {// 數(shù)據(jù)庫(kù)中還沒(méi)有存主題色
                    // 那就搞個(gè)默認(rèn)的主題色
                    value = AllThemeColor.Default;

                    // 存起來(lái)
                    this.saveThemeColor(value);
                }

                // 傳出去
                resolve(value);
            }
        });
    });
}


二. async-await


async-await的主要作用就是用來(lái)將一個(gè)異步任務(wù)變成同步的保屯。

// 存儲(chǔ)的數(shù)據(jù)為:{'hey': '你好'}

_read() {
    console.log(1);
    AsyncStorage.getItem('hey', (error, value) => {
        if (error) {
            console.log('讀取數(shù)據(jù)出錯(cuò):', error);
        } else {
            console.log(2);
            console.log(value);
            console.log(3);
        }
    });
    console.log(4);
}

比如上面這串代碼手负,是從數(shù)據(jù)庫(kù)里讀取一些數(shù)據(jù),因?yàn)?code>AsyncStorage.getItem這個(gè)操作是異步的姑尺,所以會(huì)依次輸出1竟终、4、2切蟋、你好统捶、3。

但有時(shí)候柄粹,我們希望確確實(shí)實(shí)從數(shù)據(jù)庫(kù)讀到了數(shù)據(jù)再執(zhí)行后面的操作喘鸟,而不是把操作放到異步操作的回調(diào)里執(zhí)行,此時(shí)就可以用async-await將一個(gè)異步任務(wù)變成同步的驻右。

async _read() {
    console.log(1);
    await AsyncStorage.getItem('hey', (error, value) => {
        if (error) {
            console.log('讀取數(shù)據(jù)出錯(cuò):', error);
        } else {
            console.log(2);
            console.log(value);
            console.log(3);
        }
    });
    console.log(4);
}

這樣什黑,代碼在執(zhí)行到await的地方就會(huì)阻塞住,直到它后面的異步操作執(zhí)行完畢堪夭,才會(huì)執(zhí)行后面的語(yǔ)句愕把,async只是個(gè)標(biāo)識(shí)符拣凹,沒(méi)什么實(shí)際的意義。這樣會(huì)依次輸出1恨豁、2嚣镜、你好、3橘蜜、4菊匿。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市计福,隨后出現(xiàn)的幾起案子捧请,更是在濱河造成了極大的恐慌,老刑警劉巖棒搜,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異活箕,居然都是意外死亡力麸,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)育韩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)克蚂,“玉大人,你說(shuō)我怎么就攤上這事筋讨“0龋” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵悉罕,是天一觀的道長(zhǎng)赤屋。 經(jīng)常有香客問(wèn)我,道長(zhǎng)壁袄,這世上最難降的妖魔是什么类早? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮嗜逻,結(jié)果婚禮上涩僻,老公的妹妹穿的比我還像新娘。我一直安慰自己栈顷,他們只是感情好逆日,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著萄凤,像睡著了一般室抽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蛙卤,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天狠半,我揣著相機(jī)與錄音噩死,去河邊找鬼。 笑死神年,一個(gè)胖子當(dāng)著我的面吹牛已维,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播已日,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼垛耳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了飘千?” 一聲冷哼從身側(cè)響起堂鲜,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎护奈,沒(méi)想到半個(gè)月后缔莲,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡霉旗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年痴奏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厌秒。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡读拆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鸵闪,到底是詐尸還是另有隱情檐晕,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布蚌讼,位于F島的核電站辟灰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏篡石。R本人自食惡果不足惜伞矩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望夏志。 院中可真熱鬧乃坤,春花似錦、人聲如沸沟蔑。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)瘦材。三九已至厅须,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間食棕,已是汗流浹背朗和。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工错沽, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人眶拉。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓千埃,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親忆植。 傳聞我的和親對(duì)象是個(gè)殘疾皇子放可,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 弄懂js異步 講異步之前,我們必須掌握一個(gè)基礎(chǔ)知識(shí)-event-loop朝刊。 我們知道JavaScript的一大特點(diǎn)...
    DCbryant閱讀 2,713評(píng)論 0 5
  • 你不知道JS:異步 第三章:Promises 在第二章耀里,我們指出了采用回調(diào)來(lái)表達(dá)異步和管理并發(fā)時(shí)的兩種主要不足:缺...
    purple_force閱讀 2,070評(píng)論 0 4
  • Promise 對(duì)象 Promise 的含義 Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函...
    neromous閱讀 8,708評(píng)論 1 56
  • 你不知道JS:異步 第三章:Promises 接上篇3-1 錯(cuò)誤處理(Error Handling) 在異步編程中...
    purple_force閱讀 1,400評(píng)論 0 2
  • 概述 Promise 對(duì)象是 JavaScript 的異步操作解決方案拾氓,為異步操作提供統(tǒng)一接口冯挎。它起到代理作用(p...
    nucky_lee閱讀 972評(píng)論 0 1