概述
- 同步与异步的差异
- 事件循环与消息队列 ,即如何实现异步模式
- 异步编程的方式
- Promise 异步方案、宏任务/微任务
- Generator异步方案、Async/Await语法糖
同步模式
- 逐行执行
- 阻塞
异步模式
- 不会等待任务是否执行完成,立即执行下个任务
- 后续逻辑通过回调函数定义
- 代码混乱
异步分析
同步代码按文档顺序执行,碰见异步代码,先压入调用栈,之后直接弹出到异步api环境中,继续执行同步代码,在执行同步代码的同时,事件循环一直会等待消息对列中的异步代码完成,完成后事件循环压入到调用栈中进行执行。
异步编程的回调函数
可以理解想要做的一件事情,并不知道所要依赖的事情什么时候完成。交给依赖任务的执行者,当依赖任务执行完成,执行想要做的事情。
Promise编程
基本用法
// Promise构造函数接收一个函数作为参数,作为参数的函数有两个参数
// resolve参数的类型是一个函数,将对象的状态修改为成功
// resolve函数的参数,是异步任务的操作成功的结果
// reject参数的类型是一个函数,将对象的状态修改为失败
// reject函数的参数,是异步任务失败的原因
const promise = new Promise(function(resolve,reject){
resolve(100)
// reject(new Error('promise rejected'))
})
promise.then()
promise Ajax请求
// Promise 方式的 AJAX
function ajax (url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest()
xhr.open('GET', url)
// 设置响应类型
xhr.responseType = 'json'
xhr.onload = function () {
if (this.status === 200) {
resolve(this.response)
} else {
reject(new Error(this.statusText))
}
}
xhr.send()
})
}
ajax('/api/urls.json').then(function (res) {
console.log(res)
}, function (error) {
console.log(error)
})
Promise的链式调用
- then方法会返回一个全新的Promise
- then的resolve方法的返回是下个Promise resolve的参数值 reject同理
- 后一个then方法就是在为上一Promise注册回调
- 如果回调中返回的是promise,那么后面的then方法的回调会等待它的结果,为我们返回的Promise注册回调
ajax('/api/users.json')
.then(function (value) {
console.log(1111)
return ajax('/api/urls.json')
}) // => Promise
.then(function (value) {
console.log(2222)
console.log(value)
return ajax('/api/urls.json')
}) // => Promise
.then(function (value) {
console.log(3333)
return ajax('/api/urls.json')
}) // => Promise
.then(function (value) {
console.log(4444)
return 'foo'
}) // => Promise
.then(function (value) {
console.log(5555)
console.log(value)
})
Promise异常
-
reject 就是对异常的处理
-
then方法中的rejec只能捕获上一个promise的异常
-
promise中的异常能够传递给下一个promise catch方法直接捕获异常
-
在window对象上绑定unhandledrejection世界可以捕获那些没有被手动捕获的异常
// 不推荐使用,要手动捕获
window.addEventListener('unhandledrejection',event=>{
const {reason,promise} = event
console.log(reason,promise)
// reason=>Promise 失败的原因
// promise => 出现异常的promise
event.preventDefault()
},false)
// node 中捕获异常
process.on('unhandledRejection',(reason,promise)=>{
console.log(reason,promise)
})
promise静态方法
- Promise.resolve(value)
- 创建一个成功的方法,成功的回调函数的参数的值为value的值
- 如果返回一个Promise,则会返回一个完全相等的Promise对象
- Promise.rejected()
promise并行执行
Promise.all(array)将多个Promise对象合并成一个,如果所有的Promise都成功,这个新的promise也会成功,如果有一个失败这个promise就会失败,成功后resolve回调接收到一个数组,即所有promise返回的结果
- 接收一个数组,数组中的每个元素都是一个Promise对象
promise.rece()子要有一个完成就会结束
promise执行顺序
- 宏任务会重新排队
- 微任务不会重新排队,优先执行,例:Promise、MutationObserver和node中的process.nextTick
Generator异步方案
Generator生成器函数
- 执行函数是并不会立即调用函数,返回一个生成器对象
语法:
function * foo(){
console.log('start')
// yield 'foo'
try{
const res = yield 'foo'
console.log(res)
}catch(e){
console.log(e)
}
// 可以捕获generator.throw()方法抛出的异常
}
const generator = foo() // 返回一个生成器对象
const result = generator.next() // 调用next()方法函数开始执行,返回一个对象
/*
result 对象
value yield返回的值
done 表明generator是否执行完了
*/
generato.throw(new Error('Generator error'))