1. 程式人生 > >es6學習筆記--promise對象

es6學習筆記--promise對象

遍歷 請求超時 settime start 兩個 param 接受 鏈式 handler

Promise對象是為了簡化異步編程。解決回調地獄情況 Promise,簡單說就是一個容器,裏面保存著某個未來才會結束的事件(通常是一個異步操作)的結果。從語法上說,Promise 是一個對象,從它可以獲取異步操作的消息。 Promise對象用於延遲(deferred) 計算和異步(asynchronous ) 計算。一個Promise對象代表著一個還未完成,但預期將來會完成的操作。 Promise是一個對象,可以用構造函數來創建一個Promise實例。
let promise = new Promise((resolve, reject) =>{
    // .... some coding
if (true){ // 異步操作成功 resolve(value); } else { reject(error); } }) promise.then(value=>{ // 成功的回調函數 }, error=>{ // 失敗後的回調函數 })
params:傳參是一個回調函數。這個回調函數有兩個參數resolve和reject。     resolve: 將Promise對象的狀態從“未完成”變為“成功”(即從 pending 變為 resolved),在異步操作成功時調用,並將異步操作的結果,作為參數傳遞出去.       (簡單來說就是成功了的執行)     reject: 將Promise對象的狀態從“未完成”變為“失敗”(即從 pending 變為 rejected),在異步操作失敗時調用,並將異步操作報出的錯誤,作為參數傳遞出去。       (簡單來說就是失敗了的執行) promise之後then的參數:     第一個參數是成功的回調函數,必選     第二個參數是失敗的回調函數,可選
let promise = new
Promise((resolve, reject) =>{ console.log(‘開始‘) if (2 > 1){ // 異步操作成功 resolve({name:‘peter‘,age:25}); } else { reject(error); } }) promise.then(value=>{ // 成功的回調函數 console.log(value) }, error=>{ // 失敗後的回調函數 console.log(error) }) // 開始 // {name: "peter", age: 25}
let promise = new Promise((resolve, reject) =>{
    console.log(‘開始‘)
    if (2 > 3){   // 異步操作成功
        resolve(a);
    } else {
        reject(‘未知錯誤‘);
    }
})
promise.then(value=>{
    // 成功的回調函數
    console.log(value)
}, error=>{
    // 失敗後的回調函數
    console.log(error)
})
// 開始
// 未知錯誤

Promise的特點:

  1 對象的狀態不受外界影響。Promise對象代表一個異步操作,有三種狀態:pending(進行中)、fulfilled(已成功)和rejected(已失敗)。只有異步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。   2 一旦狀態改變,就不會再變,任何時候都可以得到這個結果。就是成功了就一直是成功的狀態,失敗一直是失敗的狀態

promise先按順序實行完promise實例中方法再實行then中的resolve或者reject.

let promise = new Promise((resolve, reject)=>{
    console.log(‘promise‘)
    if (2 > 1){   // 異步操作成功
        resolve({name:‘peter‘,age:25});
    } else {
        reject(error);
    }
    console.log(‘end‘)
})
promise.then(
    value=>{
        console.log(value)
    },
    error=>{
        console.log(error)
    }
)
// promise
// end 
// {name: "peter", age: 25}

promise封裝Ajax的例子

const getJSON = function (url) {
    const promise = new Promise(function (resolve, reject) {
        const handler = function () {
            if (this.readyState !== 4) {
                return;
            }
            if (this.status === 200) {
                resolve(this.response);
            } else {
                reject(new Error(this.statusText));
            }
        };
        const client = new XMLHttpRequest();
        client.open("GET", url);
        client.onreadystatechange = handler;
        client.responseType = "json";
        client.setRequestHeader("Accept", "application/json");
        client.send();
    });
    return promise;
};

getJSON("xxxxx").then(function (json) {
    console.log(‘Contents: ‘ + json);
}, function (error) {
    console.error(‘出錯了‘, error);
});
Promise方法:

then() 為 Promise 實例添加狀態改變時的回調函數 ,上面已經提起過.

params: 第一個參數是resolved狀態的回調函數, 必選     第二個參數是rejected狀態的回調函數, 可選 ps: then方法返回的是一個新的Promise實例(註意,不是原來那個Promise實例)。因此可以采用鏈式寫法,即then方法後面再調用另一個then方法。
function start() {
    return new Promise((resolve, reject) => {
        resolve(‘start‘);
    });
}
start()
    .then(data => {
        // promise start
        console.log(data);
        return Promise.resolve(1); // p1
    })
    .then(data => {
        // promise p1
        console.log(data);
    })
// start
// 1

promise的鏈式編程,就是第一個的Promise實例的返回的值作為下一個Promise實例的參數。

catch() 用於指定發生錯誤時的回調函數 和then一樣,存在鏈式

返回一個Promise對象,如果該對象狀態變為resolved,則會調用then方法指定的回調函數;如果異步操作拋出錯誤,狀態就會變為rejected,就會調用catch方法指定的回調函數,處理這個錯誤。
function start() {
    return new Promise((resolve, reject) => {
        resolve(‘start‘);
    });
}
start()
    .then(data => {
        // promise start
        console.log(data);
        return Promise.reject(1); // p1
    })
    .catch(data => {
        // promise p1
        console.log(data);
    })

ps:then方法指定的回調函數,如果運行中拋出錯誤(reject),也會被catch方法捕獲。如果運行中是正確的,則不會實行catch語句,而是then的回調

function start() {
    return new Promise((resolve, reject) => {
        if(2>3){
            resolve(‘start‘);
        }else{
            reject(‘error‘)
        }
    });
}
start()
    .then(data => {
        console.log(data);
    })
    .catch(data => {
        console.log(data);
    })
// error

try catch方法等價於promise 拋出錯誤:

// 寫法一
const promise = new Promise(function(resolve, reject) {
    try {
        throw new Error(‘test‘);
    } catch(e) {
        reject(e);
    }
});
promise.catch(function(error) {
    console.log(error);
});

// 寫法二
const promise = new Promise(function(resolve, reject) {
    reject(new Error(‘test‘));
});
promise.catch(function(error) {
    console.log(error);
})
如果鏈式中,寫了then和catch語句,運行正確,則會進行下一個then,在這個then中運行錯誤,則會拋出這個之後的catch而不是上一個catch
function start() {
    return new Promise((resolve, reject) => {
        if(4>3){
            resolve(‘start‘);
        }else{
            reject(‘error‘)
        }
    });
}
start()
    .then(data => {
        console.log(data);
        return Promise.resolve(1)
    })
    .catch(data => {
        console.log(data)
    })
    .then(data => {
        console.log(data)
        return Promise.reject(2)
    })
    .catch(data => {
        console.log(data);
    })
// start
// 1
// 2

finally() 不管promise最後的狀態,在執行完then或catch指定的回調函數以後,都會執行finally方法指定的回調函數

finally方法不接受任何回調函數作為參數,因此不知道Promise對象是resolve還是reject。該方法與Promise狀態無關,不依賴其執行結果。
function promise(){
    return new Promise((resolve, reject) => {
        resolve(‘success‘);
    })
};
promise().then(data => {
    console.log(data)
    return Promise.reject(‘fail‘)
}).catch(data =>{
    console.log(data)
}).finally(() => {
    console.log(‘end‘)
})
// success
// fail
// end

Promise.all() 將多個 Promise 實例,包裝成一個新的 Promise 實例。並行執行異步操作的能力,並且在所有異步操作執行完後才執行回調

const allPromise = Promise.all([p1, p2, p3])
上述代表將p1,p2,p3這些Promise實例包裝成allPromise,參數不一定是數組,只要是有遍歷結構就可以作為參數。 從而該實例的狀態有兩種情況:   1: 當所有的狀態都是resolve時,allPromise的狀態是resolve   2:當有一個狀態是reject,allPromise的狀態取決於第一次reject的狀態。 當全部狀態為resolve時。
function promise(){
    return new Promise((resolve, reject) => {
        console.log(1)
        resolve(‘第一個‘);
    })
};
function promise1(){
    return new Promise((resolve, reject) => {
        console.log(2)
        resolve(‘第二個‘);
    })
};
function promise2(){
    return new Promise((resolve, reject) => {
        console.log(3)
        resolve(‘第三個‘);
    })
};
Promise.all([promise(), promise1(), promise2()])
.then(data => {
    console.log(data)
})
.catch(data => {
    console.log(data)
})
// 1
// 2
// 3
// [1,2,3]
當全部狀態中有一個是reject時
function promise(){
    return new Promise((resolve, reject) => {
        console.log(1)
        resolve(‘第一個‘);
    })
};
function promise1(){
    return new Promise((resolve, reject) => {
        console.log(2)
        reject(‘第二個‘);
    })
};
function promise2(){
    return new Promise((resolve, reject) => {
        console.log(3)
        resolve(‘第三個‘);
    })
};
Promise.all([promise(), promise1(), promise2()])
.then(data => {
    console.log(data)
})
.catch(data => {
    console.log(data)
})
// 1
// 2
// 3
// 第二個
Promise.all()可以適用於初始化的場景

Promise.race() 將多個 Promise 實例,包裝成一個新的 Promise 實例。

和Promise.all()的用法一樣,唯一不同的是,Promise實例中誰先執行,就先返回執行那一方的回調函數(resolve和reject同樣的道理,誰先執行就執行誰的回調函數)
function promise(){
    return new Promise((resolve, reject) => {
        setTimeout(function(){
            console.log(1);
            resolve(‘第一個‘);
        }, 4000);
    })
};
function promise1(){
    return new Promise((resolve, reject) => {
        setTimeout(function(){
            console.log(2);
            resolve(‘第二個‘);
        }, 2000);
    })
};
function promise2(){
    return new Promise((resolve, reject) => {
        setTimeout(function(){
            console.log(3);
            resolve(‘第三個‘);
        }, 3000);
    })
};
Promise.race([promise(),promise1(), promise2()])
.then(data => {
    console.log(data)
})
.catch(data => {
    console.log(data)
})
// 2 
// 第二個
// 1
// 3
該方法可以適用於請求超時觸發回調

Promise.resolve() 返回一個新的Promise實例,並且狀態為resolve。

function fn(){
    console.log(‘success‘)
    return 1
}
Promise.resolve(fn())
.then(data => {
    console.log(data)
})
// success
// 1

Promise.reject() 返回一個新的Promise實例,並且狀態為reject。

function fn(){
    console.log(‘fail‘)
    return 2
}
Promise.reject(fn())
.then(data => {
    console.log(data)
})
.catch(data => {
    console.log(data)
})
// fail
// 2

有了Promise對象,就可以把異步操作以同步操作的流程表達出來,避免了層層嵌套的回調函數。此外,Promise對象提供了統一的接口,使得控制異步操作更加容易。

對應的筆記和實例,我放到了GitHub,https://github.com/sqh17/notes

有什麽問題請私信或留下評論,一起加油。

參考資料: 阮一峰大大的es6標準入門:http://es6.ruanyifeng.com

es6學習筆記--promise對象