node.js中的异步编程总结

1. 阻塞与非阻塞IO

IO即为输入(input)和输出(output)
阻塞与非阻塞的区别在于输入后,输入方能不能去做其他的事情,如果不能则为阻塞,反正则为非阻塞。
以点菜为例,如果在食堂点菜,点菜阿姨需要把饭打好后,才能处理下一个同学的点菜。而在餐厅,服务员下单后,将单传给厨房,自己则可以继续为其他顾客下单。
在这个例子中,把订单传给厨房作为输入,点菜阿姨因为自己既是下单也是打饭的,下单后需要处理完当前订单才能让下一个同学下单,因此是阻塞的。而在餐厅,服务员下单后传给厨房,剩下的事就不是自己的职责范围了,可以给其他顾客服务,因此是非阻塞的。

2. 异步编程之callback

调用interview方法的时候传递一个回调方法,interview执行结束的时候再调用这个回调方法,至于回调方法的参数第一个参数是err,第二个参数是返回结果都是约定俗成的

2.1 callback示例

interview(function (err, res) {
    if (err) {
        return console.log('cry')
    }
    console.log('smile')
    console.log(res) // success
})

function interview(callback) {
    setTimeout(() => {
        num = Math.random()
        console.log(num)
        if (num > 0.1) {
            callback(null, 'success')
        } else {
            callback(new Error('fail'))
        }
    }, 500)
}

2.2 捕获异常

按下面这样是捕获不到错误的,因为node的事件循环机制,setTimeout会开启一个事件,会是一个全新的调用栈, node会循环判断这个事件是否已结束(是否一直循环暂时还不清楚),抛出错误后系统会崩溃,不会被捕获到,如果把setTimeout去掉则可以捕获到

try {
    interview(function (err, res) {
        if (err) {
            return console.log('cry')
        }
        console.log('smile')
        console.log(res) // success
    })
} catch(e) {
    console.log('报错了') // 这样是抓取不到错误的
}


function interview(callback) {
    setTimeout(() => {
        num = Math.random()
        console.log(num)
        if (num > 0.4) {
            callback(null, 'success')
        } else {
            throw new Error('fail')
        }
    }, 500)
}

2.3 回调地狱

这种回调写法虽然简单,但是会带来下面这种情况,多次嵌套会出现回调地狱,代码难以阅读

interview(function(err, res) {
    if (err) {
        return console.log('cry')
    }

    interview(function(err, res) {
        if (err) {
            return console.log('cry')
        }

        interview(function(err, res) {
            if (err) {
                return console.log('cry')
            }
            console.log('interview success, smile')
        })
    })

   
})

function interview(callback) {
    setTimeout(() => {
        num = Math.random()
        console.log(num)
        if (num > 0.4) {
            callback(null, 'success')
        } else {
            callback(new Error('fail'))
        }
    }, 500)
}

3. 异步编程之Promise

在promise还没有执行结果的时候是pending状态,执行成功后是resolved状态,执行失败是rejected状态,resovle和reject都只能接收一个参数

在这里插入图片描述

3.1 promise示例

在这里插入图片描述
在这里插入图片描述

(function() {
    var promise = new Promise(function(resolve, reject) {
        setTimeout(() => {
            resolve(3);
        }, 300)
    }).then(function(res) {
        console.log(res) // 3
    }).catch(function(err) {
        console.log(err)
    })

    console.log(promise) // 打印状态,在浏览器Console中调试能看到状态的变化
})()

在浏览器中调试,查看promise的状态
在这里插入图片描述

3.2 promise解决callback回调地狱的问题

var promise = interview(1)
    .then((res) => {
        return interview(2)
    })
    .then(() => {
        return interview(3)
    })
    .then(() => {
        console.log('三轮面试都成功了')
    })
    .catch((err) => {
        // reject后的异常会被第一个catch捕获到
        console.log('第' + err.round + '轮面试失败了')
    })

function interview(round) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (Math.random() > 0.4) {
                resolve('success')
            } else {
                var error = new Error('fail')
                error.round = round
                reject(error)
            }
        }, 500)
    })
}

3.3 promise异步任务并行执行

Promise
    .all([
        interview(1),
        interview(2)
    ])
    .then(() => {
        console.log('两个并行任务都执行成功了')
    })
    .catch((err) => {
        console.log('某个任务出现了问题')
    })

4. 异步编程之async-await

await会等待后面的promise执行结束,从而达到同步的方式写异步
在这里插入图片描述

4.1 async-await示例

await后面跟着的就是promise

(async function() {
    try {
        await interview(1)
        await interview(2)
        await interview(3)
    } catch(err) {
        return console.log('第' + err.round + '轮面试失败了')
    }
    console.log('面试成功')
})()

function interview(round) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (Math.random() > 0.4) {
                resolve('success')
            } else {
                var error = new Error('fail')
                error.round = round
                reject(error)
            }
        }, 100)
    })
}

4.1 异步任务并行执行

(async function() {
    try {
        await Promise.all([interview(1), interview(2)])
    } catch(err) {
        return console.log('第' + err.round + '轮面试失败了')
    }
    console.log('面试都成功了')
})()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值