關於Promise

Promise是一種異步編程的解決方案,相比傳統回調函數更合理.編程

1.Promise當即執行性promise

let p = new Promise((resolve, reject) => {
    console.log('當即執行!');
    resolve('返回成功!')
});

console.log('promise後執行!');

p.then(value => {
    console.log(value)
});

控制檯輸出:異步

"當即執行!"
"promise後執行!"
"返回成功!"

Promise對象表示將來發生的事件,在建立promise時,做爲promise參數傳入的函數是會被當即執行的,只是其中執行的代碼能夠是異步代碼.有些人會認爲,當promise對象調用then方法時,promise接受的函數纔會執行,這是錯誤的.因此,代碼中當即執行!先於promise後執行!輸出.異步編程

2.Promise的三種狀態.函數

let p1 = new Promise((reslove, reject) => {
    reslove(1);
});
let p2 = new Promise((reslove, reject) => {
    setTimeout(() => {
        reslove(2);
    }, 500);
});
let p3 = new Promise((reslove, reject) => {
    setTimeout(() => {
        reject(3);
    }, 500);
});

console.log(p1);
console.log(p2);
console.log(p3);
setTimeout(() => {
    console.log(p2);
}, 1000);
setTimeout(() => {
    console.log(p3);
}, 1000);

p1.then(value => {
    console.log(value);
});
p2.then(value => {
    console.log(value);
});
p3.catch(err => {
    console.log(err);
});

控制檯輸出:code

Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1}
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
1
2
3
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 2}
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: 3}

Promise內部實現是一個狀態機.Promise有三種狀態: pending,resolved,rejected.當Promise剛建立完成時,處於pending狀態;當Promise中的函數參數執行了resolve後,Promise由pending狀態變成resloved狀態;若是Promise的函數參數中執行的是reject方法,那麼Promise會有pending狀態變成rejected狀態.對象

3.Promise狀態不可逆性.事件

let p1 = new Promise((reslove, reject) => {
    reslove('成功1!');
    reslove('成功2!');
});
let p2 = new Promise((reslove, reject) => {
    reslove('成功!');
    reject('失敗!');
});

p1.then(value => {
    console.log(value);
});
p2.then(value => {
    console.log(value);
});

控制檯輸出:回調函數

"成功1!"
"成功!"

Promise的狀態一旦變成resolved或rejected時,Promise的狀態和值就固定下來了,不管後續再怎麼調用reslove或是reject方法,都不能改變它的狀態和值.因此,p1中reslove('成功2!')並不能將p1的值更改成成功2!,p2中reject('失敗!')也不能將p2的狀態由resolved改變爲rejected.同步

4.鏈式調用.

let p = new Promise((resolve, reject) => {
    resolve(1);
});

p.then(value => {
    console.log(value);
    return value * 2;
}).then(value => {
    console.log(value);
}).then(value => {
    console.log(value);
    return Promise.resolve('resolve');
}).then(value => {
    console.log(value);
    return Promise.reject('reject');
}).then(value => {
    console.log(`resolve: ${value}`);
}, err => {
    console.log(`reject: ${err}`);
})

控制檯輸出:

1
2
undefined
"resolve"
"reject: reject"

Promise對象的then方法返回一個新的Promise對象,因此能夠經過鏈式調用then方法.then方法接受兩個函數做爲參數,第一個參數是Promise執行成功時的回調,第二個參數是Promise執行失敗時的回調.兩個函數只會有一個被調用,函數返回值將用做建立then返回的Promise對象.這兩個參數的返回值能夠是下面三種狀況的一種:

①:return一個同步的值,或者undefined(當沒有返回一個有效值時,默認返回undefined),then方法將返回一個resloved狀態的Promise對象,Promise對象的值就是這個返回值.
②:return另外一個Promise,then方法將根據這個Promise的狀態和值建立一個新的Promise對象返回.
③:throw一個同步異常,then方法將返回一個rejected狀態的Promise,值是該異常.

根據以上分析,代碼中的第一個then會返回一個值爲2(1 * 2),狀態爲resolved的Promise對象,於第二個then輸出的值爲2.第二個then中沒有返回值,所以將返回默認的undefined,因而在第三個then中輸出的undefined.第三個then和第四個then中分別返回一個狀態是resloved的Promise和一個狀態是rejected的Promise,依次由第四個then中的成功回調函數和第五個then中的失敗回調函數處理.
5.Promise then()回調異步性.

let p = new Promise((resolve, reject) => {
    resolve('成功!');
});

p.then(value => {
    console.log(value);
});

console.log("誰先執行?")

控制檯輸出:

"誰先執行?"
"成功!"

Promise接受的函數參數是同步執行的,可是then方法中的回調函數則是異步的,所以,成功!會在後面輸出.
6.Promise中的異常.

let p1 = new Promise((resolve, reject) => {
    foo.bar();
    resolve(1);
});

p1.then(value => {
    console.log(`p1 then value: ${value}`);
}, err => {
    console.log(`p1 then err: ${err}`);
}).then(value => {
    console.log(`p1 then then value: ${value}`);
}, err => {
    console.log(`p1 then then err: ${err}`);
});

let p2 = new Promise((resolve, reject) => {
    resolve(2);
});

p2.then(value => {
    console.log(`p2 then value: ${value}`);
    foo.bar();
}, err => {
    console.log(`p2 then err: ${err}`);
}).then(value => {
    console.log(`p2 then then value: ${value}`);
}, err => {
    console.log(`p2 then then err: ${err}`);
    return 1;
}).then(value => {
    console.log(`p2 then then then value: ${value}`);
}, err => {
    console.log(`p2 then then then err: ${err}`);
});

控制檯輸出:

p1 then err: ReferenceError: foo is not defined
p2 then value: 2
p1 then then value: undefined
p2 then then err: ReferenceError: foo is not defined
p2 then then then value: 1

Promise中的異常由then參數中的第二個回調函數(Promise執行失敗的回調)處理,異常信息將做爲Promise的值.異常一旦獲得處理,then返回後續的Promise對象將恢復正常,並會被Promise執行成功的回調函數處理.另外,須要注意p1,p2多級then的回調函數是交替執行的,這正是由Promise then回調的異步性決定的.

7.Promise.reslove().

let p1 = Promise.resolve(1);
let p2 = Promise.resolve(p1);
let p3 = new Promise((resolve, reject) => {
    resolve(1);
});
let p4 = new Promise((resolve, reject) => {
    resolve(p1);
});

console.log(p1 === p2);
console.log(p1 === p3);
console.log(p1 === p4);
console.log(p3 === p4);

p4.then(value => {
    console.log(`p4=${value}`)
});
p2.then(value => {
    console.log(`p2=${value}`)
});
p1.then(value => {
    console.log(`p1=${value}`)
});

控制檯輸出:

true
false
false
false
p2=1
p1=1
p4=1

Promise.resolve(...) 能夠接受一個值或者是一個Promise對象做爲參數.當參數是普通值時,它返回一個resolved狀態的Promise對象,對象的值就是這個參數;當參數是一個Promise對象時,它直接返回這個Promise參數.因此p1===p2.但經過new建立的Promise對象都是一個新的對象,因此後面三個比較結果都是false.另外,爲何p4的then最早調用,可是在控制檯上是最後輸出結果的呢?由於p4中resolve接受的參數是一個Promise對象p1,reslove會對p1進行解析,獲取p1的狀態和值,可是這個過程是異步的.

8.resolve v reject.

let p1 = new Promise((resolve, reject) => {
    resolve(Promise.resolve('resolve'));
});
let p2 = new Promise((resolve, reject) => {
    resolve(Promise.reject('reject'));
});
let p3 = new Promise((resolve, reject) => {
    reject(Promise.resolve('resolve'));
});

p1.then(value => {
    console.log(`p1 fulfilled: ${value}`);
}, err => {
    console.log(`p1 rejected: ${err}`);
});
p2.then(value => {
    console.log(`p2 fulfilled: ${value}`);
}, err => {
    console.log(`p2 rejected: ${err}`);
});
p3.then(value => {
    console.log(`p3 fulfilled: ${value}`);
}, err => {
    console.log(`p3 rejected: ${err}`);
});

控制檯輸出:

p3 rejected: [object Promise]
p1 fulfilled: resolve
p2 rejected: reject

Promise回調函數中的第一個參數resolve,會對Promise執行解析,即resolve的參數是Promise對象時,resolve會解析獲取這個Promise對象的狀態和值,但這個過程是異步的.p1解析後,獲取到Promise對象的狀態是resolved,所以第一個回調被執行也就是獲取value的回調;p2解析後,獲取到Promise對象的狀態rejected,所以rejected回調執行.但Promise回調函數中的第二個參數reject不具有解析能力,reject的參數會直接傳遞給then方法中的rejected回調,所以,即便p3 reject接受了一個resolved狀態的Promise,then方法中調用的依然是rejected,而且參數就是reject接受到的Promise對象.

相關文章
相關標籤/搜索