文章目錄
- 一、三個狀态
- 二、基本用法
-
- 1.舉例
- 2.使用原生Ajax
- 3.圖檔異步加載(懶加載)
- 三、then()
- 四、Promise.all()
- 五、Promise.race()
- 六、Promise.resolve()
- 七、Promise.reject()
- 八、Generator 函數與 Promise 的結合
異步程式設計解決方案
一、三個狀态
1.promise内部狀态 不受外界影響,由異步程式設計結果決定
pending進行中
fulfilled成功
rejected失敗
2.promise中的狀态 一旦發生變化不會再修改
Promise對象的狀态改變,隻有兩種可能:
從pending變為fulfilled 和 從pending變為rejected
二、基本用法
ES6 規定,Promise對象是一個構造函數,用來生成Promise執行個體
Promise構造函數接受一個函數作為參數,該函數的兩個參數分别是resolve和reject,它們是兩個函數
resolve函數的作用是,将Promise對象的狀态從“未完成”變為“成功”(即從 pending 變為 resolved),在異步操作成功時調用,并将異步操作的結果,作為參數傳遞出去;
reject函數的作用是,将Promise對象的狀态從“未完成”變為“失敗”(即從 pending 變為 rejected),在異步操作失敗時調用,并将異步操作報出的錯誤,作為參數傳遞出去
1.舉例
let promise=new Promise((resolve,reject)=>{
let status=true;
if(status){
resolve('成功');
}
else{
reject(new Error('失敗'));
}
})
//promise對象的使用
//寫法一
promise.then((res)=>{
//成功回調函數 resolve
console.log(res);
},(error)=>{
console.log(error);
})
//輸出: 成功
//寫法二
promise.then((res)=>{
//resolve
console.log(res);
}).catch(()=>{
//reject
console.log(error);
}).finally(()=>{
console.log("最終執行的代碼");
});
//輸出: 成功 最終執行的代碼
2.使用原生Ajax
function Ajax(method,url,data,callback){
var http;
if(window.XMLHttpRequest){
http=new XMLHttpRequest();
}
else{
//IE5,IE6
http=new ActiveXObject("Microsoft.XMLHTTP");
}
if(method=="get"){
if(data){
url+="?";
url+=data;
}
http.open(method,url);
http.send();
}
else{
http.open(method,url);
if(data){
http.send(data);
}
else{
http.send();
}
}
http.onreadystatechange= function () {
if(http.readyState==4&&http.status==200){
//匿名函數回調 才能把資料拿到外面使用
callback(http.response);
}
}
}
let promise=new Promise((resolve,reject)=>{
try{
Ajax('get','./city.json',null,(res)=>{
resolve(res);
});
}
catch(e){
reject(e);
}
})
promise.then((res)=>{
//resolve
console.log(res);
}).catch(()=>{
//reject
console.log(error);
}).finally(()=>{
console.log("最終執行的代碼");
});
(上面内容即為city.json的全部内容)
3.圖檔異步加載(懶加載)
異步加載要比同步加載快很多
let promise= function (src) {
return new Promise(function (resolve,reject) {
let image=new Image();
image.onload= function () {
resolve(this); //即image
}
image.onerror= function () {
reject(new Error("圖檔加載失敗"));
}
image.src=src; //相當于給浏覽器緩存了一張圖檔
})
}
let src='./1.jpg'
promise(src).then((img)=>{
console.log(img);
document.body.appendChild(img);
}).catch((error)=>{
console.log(error);
})
三、then()
1.then方法定義在原型對象Promise.prototype上
2.then方法傳回的是一個新的Promise執行個體(注意,不是原來那個Promise執行個體)。
是以可以采用鍊式寫法,即then方法後面再調用另一個then方法。
let promise=new Promise(function (resolve,reject) {
let data={
json: function () {
return {id:1};
}
}
if(data){
resolve(data);
}
else{
reject(new Error("出錯了"));
}
})
promise.then(function (res) {
// console.log(res); //{json: ƒ}
return res.json();
}).then(function (res) {
console.log(res); //{id: 1}
})
四、Promise.all()
将多個 Promise 執行個體,包裝成一個新的 Promise 執行個體
(1)隻有p1、p2、p3的狀态都變成fulfilled,p的狀态才會變成fulfilled,此時p1、p2、p3的傳回值組成一個數組,傳遞給p的回調函數。
(2)隻要p1、p2、p3之中有一個被rejected,p的狀态就變成rejected,此時第一個被reject的執行個體的傳回值,會傳遞給p的回調函數。
let p1=new Promise((resolve,rejecr)=>{
resolve(1);
});
let p2=new Promise((resolve,rejecr)=>{
resolve(2);
})
let p=Promise.all([p1,p2]);
p.then((result)=>{
console.log(result); // [1, 2]
})
let p1=new Promise((resolve,rejecr)=>{
resolve(1);
});
let p2=new Promise((resolve,rejecr)=>{
reject(new Error("失敗"));
})
let p=Promise.all([p1,p2]);
p.then((result)=>{
console.log(result);
}).catch((err)=>{
console.log(err); //Error: 失敗
})
五、Promise.race()
同樣是将多個 Promise 執行個體,包裝成一個新的 Promise 執行個體
隻要p1、p2、p3之中有一個執行個體率先改變狀态,p的狀态就跟着改變。
那個率先改變的 Promise 執行個體的傳回值,就傳遞給p的回調函數
let p1=new Promise((resolve,reject)=>{
//模拟請求 5000ms請求回來的資料
setTimeout(function () {
resolve("資料");
},5000);
});
let p2=new Promise((resolve,reject)=>{
//模拟請求 2s後按逾時處理
setTimeout(function () {
reject(new Error("逾時"));
},2000);
});
let p=Promise.race([p1,p2]);
p.then((res)=>{
console.log(res);
}).catch((err)=>{
console.log(err);
});
兩秒後,p2狀态先改變:
六、Promise.resolve()
将現有對象轉為一個新的 Promise 對象
Promise.resolve(12);
//等價
new Promise(resolve=>resolve(12));
(1)如果參數是 Promise 執行個體,那麼Promise.resolve将不做任何修改、原封不動地傳回這個執行個體。
(2)參數是一個thenable對象(即如果轉化對象存在then方法)
會預設執行自身的then方法
let obj={
then: function (resolve) {
resolve(22);
}
}
let p=Promise.resolve(obj);
p.then(function (res) {
console.log(res); //22
})
(3)不是thenable對象
let obj={id:1};
let p=Promise.resolve(obj);
p.then(function (res) {
console.log(res); //{id: 1}
})
七、Promise.reject()
也會傳回一個新的 Promise 執行個體,該執行個體的狀态為rejected
Promise.reject(new Error("失敗"));
//等價
new Promise((resolve,reject)=>reject(new Error("失敗")))
八、Generator 函數與 Promise 的結合
使用 Generator 函數管理流程,遇到異步操作的時候,通常傳回一個Promise對象
let p= function () {
return new Promise(function (resolve) {
setTimeout(function () {
resolve("資料");
},3000)
})
}
let gen= function* (){
try{
let res=yield p();
console.log(res);
}catch(e){
throw e.message;
}
}
function run(Generator){
let it=Generator(); //傳回周遊器
function go(result){
if(result.done){
return result.value;
}
return result.value.then(function (res) {
//console.log(res); //資料
return go(it.next(res));
}).catch(function (err) {
it.throw(err);
})
}
go(it.next());
}
run(gen);
//三秒後輸出: 資料