Promise
Promise 是異步編程的一種解決方案菜谣,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大桅打。它由社區(qū)最早提出和實(shí)現(xiàn)页徐,ES6 將其寫(xiě)進(jìn)了語(yǔ)言標(biāo)準(zhǔn)豌习,統(tǒng)一了用法存谎,原生提供了Promise對(duì)象。
所謂Promise肥隆,簡(jiǎn)單說(shuō)就是一個(gè)容器既荚,里面保存著某個(gè)未來(lái)才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果。從語(yǔ)法上說(shuō)栋艳,Promise 是一個(gè)對(duì)象恰聘,從它可以獲取異步操作的消息。Promise 提供統(tǒng)一的 API,各種異步操作都可以用同樣的方法進(jìn)行處理晴叨。
Promise凿宾,就是能把原來(lái)的回調(diào)寫(xiě)法分離出來(lái),在異步操作執(zhí)行完后兼蕊,用鏈?zhǔn)秸{(diào)用的方式執(zhí)行回調(diào)函數(shù)菌湃。
<div onClick={promiseClick}>開(kāi)始異步請(qǐng)求</div>
const promiseClick =()=>{
console.log('點(diǎn)擊方法被調(diào)用')
let p = new Promise(function(resolve, reject){
//做一些異步操作
setTimeout(function(){
console.log('執(zhí)行完成Promise');
resolve('要返回的數(shù)據(jù)可以任何數(shù)據(jù)例如接口返回?cái)?shù)據(jù)');
}, 2000);
});
return p
}
promiseClick().then(function(data){
console.log(data);
//后面可以用傳過(guò)來(lái)的數(shù)據(jù)做些其他操作
//......
});
控制臺(tái)打印
精髓在于:Promise只是能夠簡(jiǎn)化層層回調(diào)的寫(xiě)法,而實(shí)質(zhì)上遍略,Promise的精髓是“狀態(tài)”,用維護(hù)狀態(tài)骤坐、傳遞狀態(tài)的方式來(lái)使得回調(diào)函數(shù)能夠及時(shí)調(diào)用绪杏,它比傳遞callback函數(shù)要簡(jiǎn)單、靈活的多纽绍。所以使用Promise的正確場(chǎng)景是這樣的:
promiseClick()
.then(function(data){
console.log(data);
return runAsync2();
})
.then(function(data){
console.log(data);
return runAsync3();
})
.then(function(data){
console.log(data);
下面代碼中蕾久,使用Promise包裝了一個(gè)圖片加載的異步操作。如果加載成功拌夏,就調(diào)用resolve方法僧著,否則就調(diào)用reject方法。
function loadImageAsync(url) {
return new Promise(function(resolve, reject) {
const image = new Image();
image.onload = function() {
resolve(image);
};
image.onerror = function() {
reject(new Error('Could not load image at ' + url));
};
image.src = url;
});
}
一般來(lái)說(shuō)障簿,調(diào)用resolve或reject以后盹愚,Promise 的使命就完成了,后繼操作應(yīng)該放到then方法里面站故,而不應(yīng)該直接寫(xiě)在resolve或reject的后面(也就是說(shuō)皆怕,resolve或reject應(yīng)該是Promise中最后一行代碼)。所以西篓,最好在它們前面加上return語(yǔ)句愈腾,這樣就不會(huì)有意外。
自己的理解:
1岂津、Promise會(huì)像正常函數(shù)一樣執(zhí)行虱黄,執(zhí)行到回調(diào)resolve時(shí),也會(huì)像回調(diào)一樣執(zhí)行吮成,執(zhí)行完resolve后橱乱,根據(jù)回調(diào)resolve的執(zhí)行結(jié)果觸發(fā)狀態(tài)改變,從pendding變成resolve或reject
2赁豆、then有兩個(gè)參數(shù)仅醇,第一個(gè)參數(shù),對(duì)應(yīng)Promise的第一個(gè)參數(shù)resolve魔种,即成功后的回調(diào)函數(shù)析二,如果then的第一個(gè)回調(diào)有參數(shù),那么在Promise中調(diào)用resolve時(shí),也要傳參叶摄,如下代碼属韧;第二個(gè)參數(shù)是失敗的回調(diào)函數(shù),對(duì)應(yīng)Promise中的reject蛤吓,在Promise的邏輯中宵喂,如果有異常或者失敗会傲,可以執(zhí)行reject回調(diào)锅棕,一般不會(huì)使用。
3淌山、Promise是找個(gè)時(shí)機(jī)把then中要執(zhí)行的函數(shù)插入到Promise的執(zhí)行順序中去裸燎。實(shí)際執(zhí)行是按照代碼順序走的,從前往后執(zhí)行多個(gè)promise泼疑,比一層一層的回調(diào)看著清晰德绿。
new Promise((resolve, reject) => {
resolve(1);
console.log(2);
}).then(r => {
console.log(r);
});
es5的構(gòu)造函數(shù)
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function () {
return '(' + this.x + ', ' + this.y + ')';
};
var p = new Point(1, 2);
es6的class
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
Class 可以通過(guò)extends關(guān)鍵字實(shí)現(xiàn)繼承。子類(lèi)必須在constructor方法中調(diào)用super方法退渗,否則新建實(shí)例時(shí)會(huì)報(bào)錯(cuò)移稳。
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y); // 調(diào)用父類(lèi)的constructor(x, y)
this.color = color;
}
toString() {
return this.color + ' ' + super.toString(); // 調(diào)用父類(lèi)的toString()
}
}