異步調用和try catch

異步調用

異步調用無論是在web端仍是在 Node裏,都是很是常見的使用方式,簡單使用異步調用的時候,其實哪一種方式都無所謂,可是邏輯一複雜的時候,就要須要書寫更加謹慎,隨意地寫就會出現本身都搞不清當前這波操做返回什麼,還有error catch 不到的狀況,web 端和 Node 端都須要 catch 住 error 以做日誌分析。web

簡單的異步調用和 error catch

一、回調函數方式

doFirstThing((err, data) => {
    if (err) {
        console.log(err);
        return;
    }
    doSecondThing(data, function(err, data){
        if (err) {
            console.log(err);
            return;
        }
        doThirdThing(data, function(err, data){
            if (err) {
                console.log(err);
                return;
            }
        })
    })
})
複製代碼

二、Promise 方式

function takeLongTime(n) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(n + 200)
        },)
    })
    
}
function doThing (n) {
    return takeLongTime(n);
}
const time1 = 200;
doThing(time1)
.then(time2 => doThing(time2))
.then(time3 => doThing(time3))
.catch(err => {
    console.log(err)
})
複製代碼

上面的代碼每次異步調用遞進200ms,並把下次須要延遲的時間傳給下個異步函數promise

三、async & await

async function doThings () {
    try {
        const data1 =  await doThing(200);
        const data2 = await doThing(data1);
        const data3 = await doThing(data2);
    } catch (err => {
        console.log(err)
    }) 
    
}
複製代碼

async & await 的參數傳遞方式是否是友好多了
不少人用的時候會疑惑async 和 await 必須都上麼?跟 Promise 該如何配合使用?bash

1)單獨使用 async

async function getHello () {
    return 'hello world';
}
console.log(getHello())
複製代碼

打印出來以下:異步


能夠看到getHello返回的是一個Promise對象,async 把函數返回的直接量用Promise.resolve('hello world')進行了包裹。
因此咱們要拿到"hello world"能夠有如下兩種方式

// Promise 方式
getHello.then(value => {
    console.log(value) // => 輸出"hello world"
})
// await 方式  
const value = await getHello();
複製代碼

2)await 卻不能單獨使用

上面的 await getHello()執行的時候實際會以下錯誤async


如圖所示,await 在 async 函數中才會有效。
await 是 async wait 的縮寫,因此你應該向下面同樣wait 你的 getHello

async function asyncGetHello () {
    const value = await getHello();
}
複製代碼

3) await等待的不必定要是 async 函數

按照設計,await 等待的是一個異步函數的返回結果,有的人會覺得這個異步函數必須是一個 async 函數,但實際上 async 或者一個 Promise實例都是能夠的,甚至不是個異步函數,一個直接量也都能正確返回。函數

async function asyncDemo () {
    // await 一個 async 函數
    await getHello();  
    // await 一個 Promise 示例
    await new Promise(function (resolve, reject) {
        resolve('result');
    })
    // await 一個直接涼
    await 1+1;
}
複製代碼

Promise 的error catch 不足的地方

try{
    new Promise(function (reslove, reject) {
        throw new Error('有 error 拉');
    })
    .then(() => {
    },err => {
        console.log('failCallback',err)
    })
    .catch(err => {
        console.log('promise catch error', err)
    })
} catch (err) {
    console.log('try catch error', err)
}

複製代碼

代碼執行後實際以下ui


Promise會優先在 failback 裏報錯,沒有 failback 函數,會在 Promise 的catch裏執行,永遠永遠不會跑到try catch 裏面。
單個執行沒有問題,可是函數裏有三四個 Promise 呢,錯誤處理就變得繁瑣和易錯,並且只能覆蓋本身當前的 Promise 實例。
相比之下,上面 async 和 await 的 try catch 是否是強大和簡潔多了。

map和 await 的配合使用

try {
    [1,2,3].map(async (data) => {
        await doThing();
    })
} catch (err) {
    console.log('try catch error', err)
}
複製代碼

上面的代碼永遠不會 catch 到 error
Node 端能夠在下面的事件中 catch 住spa

process.on('unhandledRejection', (reason, p) => {
    logger.error('Unhandled Rejection at:', p, 'reason:', reason);
});
複製代碼

但若是咱們不想要在unhandledRejection的回調裏處理,仍是想在 try catch 裏統一處理呢,能夠用以下方式設計

try {
    async function map&async() {
        await Promise.all([1,2,3].map(async (data) => {
            await doThing();
        }));
    }
} catch (err) {
    console.log('try catch error', err)
}
複製代碼
相關文章
相關標籤/搜索