1. 程式人生 > 其它 >promise async await

promise async await

技術標籤:jsjs

  • 首先定義一個函式
let func1 = () => new Promise((resolve, reject) => setTimeout(() => resolve(12345), 1000))

函式func1執行的時候,會返回一個promise物件

let func1 = () => new Promise((resolve, reject) => setTimeout(() => resolve(12345), 1000))
let result = func1()
console.log(result);

在這裡插入圖片描述

  • 使用async和await後
    let func1 = () => new Promise((resolve, reject) => setTimeout(() => resolve(12345), 1000))
    // 當且僅當async修飾函式後,函式內可以使用await,await後面可以跟一個返回promise的函式
    async function func2() {
    // await會拿到resolve結果,是then函式的語法糖
        let res = await func1()
        console.log(res);
    }
    func2()

一秒鐘之後打印出12345
在這裡插入圖片描述

  • 上面的函式可以寫成這樣的形式
    let func1 = () => new Promise((resolve, reject) => setTimeout(() => resolve(12345), 1000))

    function func2() {
        func1().then(res => console.log(res))
    }
    func2()

在1秒鐘之後會打印出12345
在這裡插入圖片描述
async + await(是promise + then的語法糖)(可以認為是generator函式的語法糖)
上面兩種方式是等價的,只不過使用async和await可以像同步程式設計一樣整理程式碼邏輯,不想then那樣回撥地獄

await拿的是resolve的資料或者說傳給then的資料,reject的需要靠try…catch

async function main() {
	try {
		var data1 = await query(sql)
		...
		var data2 = await query(sq2)
		...
		var data3 = await query(sq3)
	} catch(e) {
		console.log(e)
	}
}

這樣可以對三條語句同時處理錯誤

  • 使用async await處理非同步請求
async function get() {
	let user = await ajax('/user')
	// 等待user請求回來之後,再請求lesson
	let lessons = await ajax('/lessons')
	// lessons請求回來之後再進行其它的操作
	console.log(lessons)	
}
get()
  • async延時函式
    function sleep(delay = 2000) {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve();
            }, delay)
        })
    }
    async function show() {
        for (let value of ['hello', 'world', '123']) {
        // 延遲2秒之後再列印
            await sleep();
            console.log(value);
        }
    }
    show()
  • class與await結合
如果一個類中包含一個then方法,那麼這個then就會包裝成一個Promise
    class User {
        constructor(name) {
            this.name = name;
        }
        then(resolve, reject) {
            let user = ajax(`http://localhost3000/user?name=${this.name}`);
            resolve(user);
        }
    }
    async function get() {
    // 名字請求回來之後在列印
        let user = await new User('xiaoming');
        console.log(user);
    }
    get()
  • await並行執行技巧
    function func1() {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve(123)
            }, 2000)
        })
    }
    function func2() {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve(456)
            }, 2000)
        })
    }
    async function demo() {
        let h1 = func1();
        let h2 = func2();
        let result1 = await h1;
        let result2 = await h2;
        // 這樣func1和func2就可以一起執行,得到他們的結果後再列印,還可以通過Promise.all實現
        console.log(result1, result2);
    }
    demo()

通過Promise.all實現

    function func1() {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve(123)
            }, 2000)
        })
    }
    function func2() {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve(456)
            }, 2000)
        })
    }
    async function demo() {
        let result = await Promise.all([func1(), func2()])
        console.log(result);
    }
    demo()

Promise規範–all
all方法用於監聽多個Promise物件
引數是一個數組,陣列中的每一項都是一個Promise物件
我們可以通過then方法監聽狀態的改變
如果所有的操作都執行成功,才會執行success方法
如果有一個操作執行失敗,則會執行fail方法
不論是成功還是失敗,返回值是陣列,陣列中的每一個成員對應每一個Promise返回的資料

Promise規範–race
race方法用於監聽多個Promise物件
引數是一個數組,陣列中的每一項都是一個Promise物件
我們可以通過then方法監聽狀態的改變(監聽第一個Promise物件狀態的改變)
如果有一個請求執行成功,就會執行success方法
如果有一個請求執行失敗,則會執行fail方法
返回值是狀態改變的時候傳遞的資料

簡單實現Promise

        // 實現promise
        function MyPromise(callBack) {
            // 維護狀態
            this.status = 'pendding';
            // 儲存回撥函式
            this.successArray = [];
            this.failArray = [];

            // 定義resolve和reject方法
            // 成功
            let resolve = (value) => {
                // 改變狀態
                this.status = 'resolved';
                // 執行回撥函式
                this.successArray.forEach(fn => value = fn(value))
                this.successArray = [];
                this.value = value;
            }
            // 失敗
            let reject = () => {
                this.status = 'rejected';
                this.failArray.forEach(fn => value = fn(value))
                this.failArray = [];
                this.value = value
            }

            // 執行回撥函式
            try {
                callBack(resolve, reject);
            } catch(e) {
                // 有錯誤就失敗了
                reject(e);
            }
        }
        // 原型方法
        MyPromise.prototype.then = function(success, fail) {
            if (this.status === 'padding') {
                success && this.successArray.push(success);
                fail && this.failArray.push(fail);
            } else if (this.status === 'resolved') {
                success && success(this.value);
            } else {
                fail && fail(this.value);
            }

            // 鏈式呼叫
            return this;
        }