chiwent / blog

个人博客,只在issue内更新
https://chiwent.github.io/blog
8 stars 0 forks source link

处理js的异步逻辑 #8

Open chiwent opened 5 years ago

chiwent commented 5 years ago

优雅地处理js的异步

处理串行异步逻辑

    在很多业务逻辑中,我们需要串行处理多个异步的操作,在早期的方法中,我们可以使用Promise.all来处理,一个任务列表按顺序依次执行(网上一些文章说是并行执行?? 参考这里的讨论:cnode),当有其中一个rejected,返回的就是rejected。如果是用race,假如队列中有任意一项出错,整个队列都不会有输出结果,虽然说结果是一样的,但是race的执行时间取决于执行最快的那个 promise,而all的执行时间取决于执行最慢的那个 promise。假如我们单纯用promise来处理逻辑,其链式调用的格式比较粗糙。当我们引用async/await时,我们不仅可以轻松实现不同的逻辑(改动的内容较小),并且还可以让代码看起来更像是同步的

var arr = [100, 300, 400, 200]

function newError() {
    return new Promise((resolve, reject) => {
        throw new Error('Throw Error')
    })
}

function setTime(time){
  return new Promise((resolve, reject)=>{
    if (time <= 300 && resolve) {
        setTimeout(()=>resolve(time),time);
    } else if (time > 300 && reject) {
        reject('Error in', time)
    }
  })
}

// Promise.all只要有一个失败,就会rejected
Promise.all([setTime(300), setTime(400), setTime(100)]).then(val => {
    console.log(val)
})

// Promise.race一旦遇到错误,就会退出
Promise.race([setTime(200), setTime(100), setTime(400)]).then(val => {
    console.log(val)
})

// 通过then链式调用的方法,一旦某个任务出现错误,那么最后的状态就为rejected,后面的任务不执行(前面正确的依旧正常输出)
setTime(300).then(val => {
    console.log(val)
    return newError()
}).then(val => {
    console.log(val)
    return newError()
}).then(val => {
    console.log(val)
}).catch(err => {
    console.log(err)
})

// 我们可以将promise实例放到async/await的循环内处理,这样无论任意的promise是否出错,所有的promise都会执行
async function asyncPromise(arr, handler) {
    let result = []
    for (let i of arr) {
        let wait;
        try {
            wait = await handler(i)
        } catch (err) {
            console.log('catch Error')
        }
        result.push(wait) 
    } 
    return result;
}

asyncPromise(arr, setTime).then(val => {
    console.log(val)
})

// 使用async/await来封装promise任务队列有一个很灵活的地方,假如再for循环中有任意一个任务出错,那么我们可以再try/catch将其捕获,然后break跳出循环,这样,一旦中间出现了错误,就可以中途退出
async function asyncPromise(arr, handler) {
    let result = []
    for (let i of arr) {
        let wait;
        try {
            wait = await handler(i)
        } catch (err) {
            console.log('catch Error:', err)
            break
        }
        result.push(wait) 
    } 
    return result;
}

asyncPromise(arr, setTime).then(val => {
    console.log(val)
})
chiwent commented 5 years ago

一些推荐文章: