## Promise 對象
> 1.Promise 的含義
2.基本用法
3.Promise.prototype.then()
4.Promise.prototype.catch()
5.Promise.prototype.finally()
6.Promise.all()
7.Promise.race()
### Promise的含義
同步和異步
在JavaScript的世界中,所有js代碼都是單線程執行的,但是瀏覽器內部還有其他線程,比如瀏覽器事件,網絡請求等都是其他線程在管理。而且這些操作都是相當耗時的。
如果這些也都是單線程的,那js在執行的時候,就不得不停下來等這些耗時的任務完成了才能繼續向下執行。這會導致交互的延遲,體驗極差。
為了解決這個問題了,我們將這些耗時的操作呢,處理成異步。就是如果觸發請求,請求比較耗時,就先將耗時請求交給其他線程處理,js的主線程繼續向下執行。等耗時的操作處理完畢后,通知js主線程執行回調。

~~~
$.ajax({
success:function(res){
var res = res
// 此處省略一萬行代碼
},
fail:function () {
}
})
~~~
~~~
asyncFunc1(opt, (...args1) => {
asyncFunc2(opt, (...args2) => {
asyncFunc3(opt, (...args3) => {
asyncFunc4(opt, (...args4) => {
// some operation
});
});
});
});
~~~
這就是所謂的回調地獄。回調嵌套導致了代碼閱讀性差,可復用性差。
我們希望這樣的異步可以:
1.請求數據和處理數據能夠分離開
2.代碼可閱讀性高
3.代碼可復用性高
一般我們是采用如下的代碼來處理
~~~
function cb(data) {
//處理data的n行代碼
}
function errorcb(){
//處理請求失敗的情況
}
function ajax(cb,errorcb) {
$.ajax({
success:function(data){
cb&&cb(data)
},
fail:function(){
errorcb&&errorcb()
}
})
}
ajax(cb,errorcb);
~~~
Promise寫法,Promise集中管理異步請求的運行狀態。回調函數處理正常或者異常操作。將ajax的請求狀態邏輯和回調邏輯徹底分離開。
~~~
promise.then(function(value){
//成功的處理函數
},function(error){
//失敗的處理函數
});
~~~
Promise 是異步編程的一種解決方案。除此之外還有Generator函數
ES6 將其寫進了語言標準,統一了用法,原生提供了Promise對象。
Promise對象有以下兩個特點
(1)對象的狀態不受外界影響
(2)一旦狀態改變,就不會再變,任何時候都可以得到這個結果
三種狀態:
pending:進行中
fulfilled :已經成功
rejected 已經失敗
狀態改變:
Promise對象的狀態改變,只有兩種可能:
從pending變為fulfilled
從pending變為rejected。
這兩種情況只要發生,狀態就凝固了,不會再變了
### 基本用法
~~~
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 異步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
~~~
~~~
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'done');
});
}
timeout(100).then((value) => {
console.log(value);
});
~~~
### Promise.prototype.then()
~~~
getJSON("/posts.json").then(function(json) {
return json.post;
}).then(function(post) {
// ...
});
~~~
可以連續調用then方法
~~~
getJSON("/post/1.json").then(function(post) {
return getJSON(post.commentURL);
}).then(function funcA(comments) {
console.log("resolved: ", comments);
}, function funcB(err){
console.log("rejected: ", err);
});
~~~
### Promise.prototype.catch()
~~~
getJSON('/posts.json').then(function(posts) {
// ...
}).catch(function(error) {
// 處理 getJSON 和 前一個回調函數運行時發生的錯誤
console.log('發生錯誤!', error);
});
~~~
### Promise.prototype.finally()
~~~
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
~~~
~~~
server.listen(port)
.then(function () {
// ...
})
.finally(server.stop);
~~~
### Promise.all()
~~~
const p = Promise.all([p1, p2, p3]);
~~~
~~~
// 生成一個Promise對象的數組
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
return getJSON('/post/' + id + ".json");
});
Promise.all(promises).then(function (posts) {
// ...
}).catch(function(reason){
// ...
});
~~~
### Promise.race()
~~~
const p = Promise.race([p1, p2, p3]);
const p = Promise.race([
fetch('/resource'),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
]);
p
.then(console.log)
.catch(console.error);
~~~
上面代碼中,只要p1、p2、p3之中有一個實例率先改變狀態,p的狀態就跟著改變。那個率先改變的 Promise 實例的返回值,就傳遞給p的回調函數。
### 課后習題
1.用promise實現一個函數,按順序每隔一秒打印一個數字,范圍是1-10。
- Less
- 課程規劃
- Less概述
- 變量
- 混合
- 嵌套
- 繼承
- 導入
- 函數
- 其他
- 實戰
- ES6
- 課程規劃
- ES6概述
- let和const命令
- 變量的解構賦值
- 字符串擴展
- 函數擴展
- 數組擴展
- Set和Map數據結構
- Symbol
- Generator 函數
- Promise對象
- Class語法
- Module 的語法
- ES7和ES8
- 實戰
- VUE
- 課程規劃
- vue概述
- vue實例
- 模版語法
- 計算屬性和偵聽器
- Class和Style的綁定
- 條件渲染
- 列表渲染
- 事件處理
- 表單輸入綁定
- 組件基礎
- 過渡和動畫
- 自定義指令
- 過濾器
- 響應式原理
- 實戰課程
- Node
- 課程規劃
- 課程概述
- node入門實例
- 模塊系統
- 回調函數
- 全局對象
- 常用模塊介紹
- 常用模塊介紹-1
- 常用模塊介紹-2
- 常用模塊介紹-3
- npm使用
- express的使用
- express的使用-1
- webpack基礎
- 實戰
- 微信小程序
- 課程規劃
- 課程概述
- 基本配置和生命周期
- wxml模版
- wxss
- wxs
- 組件
- 微信API
- 自定義組件開發
- 實戰小程序
- Element
- 課程規劃
- 課程概述
- 特性介紹
- 組件介紹-基礎組件
- 組件介紹-表單組件
- 組件介紹-數據展示組件
- 組件介紹-提示組件
- 組件介紹-導航組件
- 組件介紹-其他組件
- 綜合案例