嗨,瞭解一下,個人Promise學習筆記

Promise

Promise 是什麼?

詞語本意:

發音:[ˈprɒmɪs]
詞性:名詞,
翻譯:許諾,允諾。

MDN解釋

  1. Promise 對象用於一個異步操做。
  2. 一個Promise表示一個如今,未來或永不可能可用的值。

按照書寫方式來解釋

能夠將異步操做的書寫方式變成一種隊列化的書寫方式,並按照咱們寫的那樣的預期來執行返回符合預期的結果。javascript

爲何須要Promise

js爲檢查表單而生,其首要目標是操做dom,界面凍結會形成很是不友好的用戶體驗,因此dom操做大可能是異步的。
注意:同步操做的處理器未執行完成會使得界面沒法響應用戶的其餘操做,而異步操做則能夠避免該問題。
常見的異步操做語法:java

1. 異步事件

$('#start').on('click',startHandler);
function startHandler(){} // 定義事件響應的處理器函數

用戶點擊start元素就會觸發一個異步事件去執行,再次觸發沒必要等待前一次事件執行完成,就能夠再次觸發。node

2. 回調函數

$.ajax('http://baidu.com',{
    success:function(res){
    // 成功回調處理器
    },
    error:function(e){
    // 失敗回調處理器
    }
});

用戶發送一個向百度服務器獲取數據的異步請求ajax

3. 無阻塞高併發的node的誕生

更加嚴重的依賴異步操做才能完成無阻賽高併發的特性。數組

然而異步回調這種方式並非理想的,它卻有一些問題,
好比:promise

  1. 回調地獄這種難於維護的書寫方式。

更深層次的問題:服務器

  1. 嵌套回調中的循環語句出錯後,沒法正常的使用return和throw終止
  2. 沒法正常檢索堆棧信息(每個回調都會從新創建堆棧)
  3. 多個回調之間難以創建聯繫

Promise詳解

一個promise的基本使用案例:併發

new Promise(
    // 執行器 executor
    function ( resolve, reject ) {
        //一段耗時很長的異步操做
        resolve(); //異步處理成功
        reject(); // 異步處理失敗 
        //注意:resolve和reject這倆個回調函數被調用是互斥的  
    }
).then( function A(){
            //成功,下一步
    }, 
    function B(){
        //失敗,作善後處理
    } 
);
  1. promise是一個代理對象,它和原先要進行的操做並沒有關係。
  2. 它經過引入一個回調,避免更多的回調。
promise有三個狀態:

pending 初始狀態 fulfilled 操做成功 rejectd 操做失敗dom

  1. promise一經建立,執行器便會馬上執行;
  2. 異步操做經過調用resolve改變promise狀態爲fulfilled,經過調用reject改變promise狀態爲rejected;
  3. promise狀態發生改變就會觸發then裏面的響應函數;
  4. promise狀態一經改變,不會再變。
promise最簡單的實現:
//範例1
console.log('here we go');
new Promise( resolve => {
    setTimeout( () => {
        resolve('hello');
    }, 2000);
}).then( value => {
    console.log( value + ' world');
});
/* 控制檯日誌 */ 
here we go
// 2s之後
hello world
// 範例2
console.log('here we go');
new Promise(resolve => {
    setTimeout( () => {
        resolve('hello');
    }, 2000);
}).then(value => {
    console.log(value);
    return new Promise( resolve => {
        setTimeout(() => {
            resolve('world');
        }, 2000);
    });
}).then(value => {
    console.log( value + ' world');
});
/* 控制檯日誌 */
here we go
// 2s後
hello
// 2s後
world world

// 假如一個Promise已經完成了,再.then()會怎樣?異步

console.log('start');
let promise = new Promise(resolve => {
    setTimeout(() => {
        console.log('the promise fulfilled');
        resolve('hello, world');
    }, 1000);
});
setTimeout(() => {
    promise.then( value => {
        console.log(value);
    });
}, 3000);
/* 控制檯 */
17:37:29.015 start
17:37:30.016 the promise fulfilled
17:37:32.017 hello, world

// 假如在.then()的函數裏面不返回新的Promise,會怎樣?

console.log('here we go');
new Promise(resolve => {
    setTimeout( () => {
        resolve('hello');
    }, 2000);
}).then( value => {
    console.log(value);
    console.log('everyone');
    (function () {
        return new Promise(resolve => {
            setTimeout(() => {
                console.log('Mr.Laurence');
                resolve('Merry Xmas');
            }, 2000);
        });
    }());
//     return false;
}).then( value => {
    console.log(value + ' world'); return 0
}).then( value => {
    console.log(value + ' world');
}).then( value => {
    console.log(value + ' world');
});
/* 控制檯 */
17:53:03.175 here we go
17:53:03.191 Promise {<pending>}
17:53:05.181 hello
17:53:05.181 everyone
17:53:05.181 undefined world
17:53:05.182 0 world
17:53:05.182 undefined world
17:53:07.187 Mr.Laurence
從日誌能夠看出,
1. 執行器中必須回調resolve或者reject改變promise的狀態;
2. 當狀態改變後繼續調用then方法,可是promise中的狀態已經沒法改變了;
3. 能夠看到promise對象幫咱們生成了一個隊列,這個隊列一直存在。
then方法
  1. then() 接受倆個狀態響應函數參數,分別表明fulfilled和rejected
  2. then() 返回一個新的Promise實例,因此它能夠鏈式調用
  3. 狀態響應函數能夠返回新的Promise,其餘值,或者不返回值
  4. 若是返回新的Promise,那麼下一級.then()會在新的promise狀態改變以後執行
  5. 若是返回其它任何值,則會馬上執行下一級.then()
  6. then裏面有then的狀況
    1). 由於.then()返回的仍是Promise實例。
    2). 會等裏面的.then()執行完,在執行外面的。
    3). 對咱們來講,此時最好將其展開,會更好閱讀。

測試
問題:下面四種Promise的區別是什麼?

前提:doSomething方法和doSomethingElse方法均返回一個promise實例。
// #1
doSomething().then(function() {
    return doSomethingElse();
});
// #2
doSomething().then(function(){
    doSomethingElse();
});
// #3
doSomething().then(doSomethingElse());
// #4
doSomething().then(doSomethingElse);
// 解析:
// #1
doSomething().then(function() {
    return doSomethingElse();
});
//符合預期的,能夠繼續回調then方法獲取doSomethingElse的結果
// #2
doSomething().then(function(){
    doSomethingElse();
});
//then中沒有返回promise,因此以後的then沒法獲取到doSomethingElse的結果,而且與doSomethingElse幾乎同時執行
// #3
doSomething().then(doSomethingElse());
// then應該接收一個狀態處理函數,當前這種狀況傳入了一個promise實例,沒法獲取上層promise的結果,而該層then會被忽略,下一層會獲取到doSomething()的結果
// #4
doSomething().then(doSomethingElse);
// then方法中吧doSomethingElse直接當成狀態處理函數也是能夠達到預期的
錯誤處理 catch方法

catch和then同樣會返回一個promise實例。若是沒有拋出錯誤,該實例默認也會返回fulfilled狀態。

Promise 經常使用函數

promise.all
接收一個數組參數,返回一個新的promise實例,響應函數中的結果爲數組中的每一個promise的結果。
與map連用
使用forEach和reduce實現隊列
ES2017 的async/await

該學習筆記是學習慕課網中 Promise入門 記錄

相關文章
相關標籤/搜索