同步模式
由于JavaScript是单线程,因此JavaScript代码会自上而下执行代码
- 如果其中有耗时操作,那么就会阻塞程序执行,使得界面卡死
异步模式
异步任务不会等待执行结束再执行下面的代码,代码执行顺序会比较跳跃
console.log("global start")setTimeout(function timer1() {console.log("timer1 invoke")},1800)setTimeout(function timer2() {console.log("timer2 invoke")setTimeout(function inner() {console.log("inner invoke")},1000)},1000)console.log("global end")// 执行结果global startglobal endtimer2 invoketimer1 invokeinner invoke
- 首先JavaScript会自上而下执行,遇到settimeout时候将其放在异步线程中倒计时,所有同步代码都自上而下执行,因此会先执行console打印global start 和 global end
- 然后定时器执行结束之后会将里面的代码推入异步队列,事件循环中执行,因此timer2先打印,time2里面定时器又被搁置一边,事件循环继续将timer1推入主栈中执行
- 最后inner定时器将里面代码推入异步队列,异步队列推送主栈中执行

同步或异步指的是运行环境所提供的API是同步还是异步模式执行的
回调函数
调用者定义函数传递给执行者执行,其实就是调用者告诉执行者异步任务结算书后应该做什么
function foo (callback) {setTimeout(function () {callback()},3000)}foo(function () {console.log("这就是一个回调函数")})
Promise
用来解决回调函数嵌套过多的问题,承诺执行异步任务,成功之后做什么,失败后怎么办都是事先定义好的 分为三个状态:pending,resolve,reject
- 基本用法 ```javascript const promise = new Promise((resolve, reject)=>{ resolve(100) // 承诺成功 })
promise.then(value => { console.log(“resolved”,value) }, error => { console.log(“rejected”, error) })
- 案例```javascriptfunction 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()})}
- 常见误区
- 如果发送多次请求,每次请求都依赖上一个请求的返回结果,写法不注意也会出现promise嵌套过多的情况出现
- 链式调用
promise.then会返回一个全新的promise形成promise链 then当中promise是什么状态,下一个then就会帮忙处理这个状态
Promise.then(val=>{return Promise.resolve(val)}).then(val=>{return Promise.reject(val)}).then(val=>{return Promise.resolve(val)},err=>{console.log(err)}).then(val => {return "123"}).then(val => {//这个val就是"123"}).then()
- 总结
- Promise对象的then方法会返回一个全新的promise对象
- 后面的then方法就是在为上一个then返回的Promise注册回调
- 前面then方法中回调函数的返回值回作为后面then方法回调的参数
- 如果回调中返回的是Promise,那后面then方法的回调会等待它的结束
- 异常处理
可以使用catch注册失败回调,给promise链使用 catch可以捕获所有上面Promise出现过的异常
- 异常处理
ajax().then(res=>{}).catch(err => {})
- 全局注册(不推荐)
Promise.on('unhandledRejection',(reason, promise) => {console.log(reason, promise)// reason指的是出现失败的原因,一般是一个错误对象// promise是指出现异常的Promise对象})
- 静态方法
- Promise.resolve ```javascript Promise.resolve(‘foo’) .then( val => { console.log(val) })
// Promise.resolve包裹一个promise得到的promise与包裹的promise是同一个 let promise = ajax(“/api/users”) let promise2 = Promise.resolve(promise) console.log(promise === promise2) // true
Promise.resolve({ then(onFulfilled, onRejected) { //实现了一个thenable onFulfilled(“foo”) } }).then(val => { console.log(val) // foo })
- Promise.reject```javascriptPromise.reject('anything').catch( err => {console.log(err)})
- Promise并行执行
- Promise.all
会等待所有异步任务执行结束
- Promise.all
var promise = Promise.all([ajax("/api/users"),ajax('/api/login')])promise.then( res => {console.log(res)}).catch(err => {console.log(err)})// 都成功才会走then 只要有一个失败都会走catch
- Promise.race()
只会等待第一个结束的任务
const request = ajax('/api/posts')const timeOut = new Promise((resolve, reject) => {setTimeout(() => reject(new Error('timeout')), 5000)})Promise.race([request, timeOut]).then(val => {console.log(val)}).catch(err => {console.log(err)})// 如果5秒内请求没响应就会直接结束,走到catch
- Promise 执行时序/宏任务,微任务 ```javascript console.log(“global start”)
setTimeout(() => { console.log(‘settimeout’) },0)
Promise.resolve() .then(() => { console.log(“promise”) }) .then(() => { console.log(“promise 2”) }) .then(() => { console.log(“promise 3”) })
console.log(“global end”)
// 执行结果 global start global end promise promise 2 promise 3 settimeout
> 回调队列的任务称为**宏任务**,宏任务执行过程中可以临时加上一些额外的需求> 对于这些额外的需求,可以选择作为一个**新的宏任务**进入到队列中排队> 也可以作为当前任务的**微任务**,直接在当前任务结束过后立即执行> 微任务目的提高整体响应能力- 微任务:
- Promise
- MutationObserver
- node中的process.nextTick ```
Generater 异步方案
function * foo () {console.log('start')try {const res = yield 'foo'console.log(res) // bar} catch (e) {console.log(e) // Generator error}}const generator = foo()const result = generator.next()console.log(result) // foogenerator.next("bar")generator.throw(new Error('Generator error'))
Async / Await 语法糖
async function main () {let res = await ajax('/api/users')}const promise = main()promise.then( () => {console.log('all completed')})
