發音:[ˈprɒmɪs] 詞性:名詞, 翻譯:許諾,允諾。
能夠將異步操做的書寫方式變成一種隊列化的書寫方式,並按照咱們寫的那樣的預期來執行返回符合預期的結果。javascript
js爲檢查表單而生,其首要目標是操做dom,界面凍結會形成很是不友好的用戶體驗,因此dom操做大可能是異步的。
注意:同步操做的處理器未執行完成會使得界面沒法響應用戶的其餘操做,而異步操做則能夠避免該問題。
常見的異步操做語法:java
$('#start').on('click',startHandler); function startHandler(){} // 定義事件響應的處理器函數
用戶點擊start元素就會觸發一個異步事件去執行,再次觸發沒必要等待前一次事件執行完成,就能夠再次觸發。node
$.ajax('http://baidu.com',{ success:function(res){ // 成功回調處理器 }, error:function(e){ // 失敗回調處理器 } });
用戶發送一個向百度服務器獲取數據的異步請求ajax
更加嚴重的依賴異步操做才能完成無阻賽高併發的特性。數組
然而異步回調這種方式並非理想的,它卻有一些問題,
好比:promise
更深層次的問題:服務器
一個promise的基本使用案例:併發
new Promise( // 執行器 executor function ( resolve, reject ) { //一段耗時很長的異步操做 resolve(); //異步處理成功 reject(); // 異步處理失敗 //注意:resolve和reject這倆個回調函數被調用是互斥的 } ).then( function A(){ //成功,下一步 }, function B(){ //失敗,作善後處理 } );
pending 初始狀態 fulfilled 操做成功 rejectd 操做失敗dom
//範例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對象幫咱們生成了一個隊列,這個隊列一直存在。
測試
問題:下面四種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和then同樣會返回一個promise實例。若是沒有拋出錯誤,該實例默認也會返回fulfilled狀態。
promise.all
接收一個數組參數,返回一個新的promise實例,響應函數中的結果爲數組中的每一個promise的結果。
與map連用
使用forEach和reduce實現隊列
ES2017 的async/await
該學習筆記是學習慕課網中 Promise入門 記錄