JS 异步编程

232 阅读4分钟

JS 异步编程

JavaScript异步编程

单线程: JS执行环境中负责执行代码的线程只有一个 优点: 更安全更简单 缺点: 耗时任务阻塞

同步模式---调用栈(Call stack)排队执行

异步模式

不会去等待这个任务的结束才开始下一个任务 开启过后立即往后执行下一个任务 后续逻辑一般会通过回调函数的方式定义 消息队列(Queue)和事件循环(Event loop) 运行环境提供的API是以同步或异步模式的方式工作 EventLoop 是一种循环机制 ,不断去轮询一些队列 ,从中找到 需要执行的任务并按顺序执行的一个执行模型。 消息队列 是用来存放宏任务的队列, 比如定时器时间到了, 定时间内传入的方法引用会存到该队列, ajax回调之后的执行方法也会存到该队列。 一开始整个脚本作为一个宏任务执行。执行过程中同步代码直接执行,宏任务等待时间到达或者成功后,将方法的回调放入宏任务队列中,微任务进入微任务队列。 当前主线程的宏任务执行完出队,检查并清空微任务队列。接着执行浏览器 UI 线程的渲染工作,检查web worker 任务,有则执行。 然后再取出一个宏任务执行。以此循环... 宏任务可以理解为每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)。 浏览器为了让 JS 内部宏任务 与 DOM 操作能够有序的执行,会在一个宏任务执行结束后,在下一个宏任务执行开始前,对页面进行重新渲染。 宏任务包含:script(整体代码)、setTimeout、setInterval、I/O、UI交互事件、MessageChannel 等 微任务可以理解是在当前任务执行结束后需要立即执行的任务。也就是说,在当前任务后,在渲染之前,执行清空微任务。 所以它的响应速度相比宏任务会更快,因为无需等待 UI 渲染。 微任务包含:Promise.then、MutaionObserver、process.nextTick(Node.js 环境)等

Promise

三个状态 Pending Fulfilled-onFulfilled Rejected-onRejected 状态更改之后不可修改

promise 基本用法

const promise = new Promise(function(resolve, reject){ // foo() // throw new Errow('error') resolve(100)

// reject(new Error("promise rejected"))

}) // promise.then(function(value){ // console.log('resolved', value) // }, function(error){ // console.log('rejected', error) // }) // console.log('end')

Promise 常见误区---回调嵌套

Promise 链式调用

then方法会返回一个全新的Promise对象 后面的then方法就是在为上一个then返回的Promise注册回调 前面then方法中的回调函数的返回值会作为后面then方法回调的参数 如果回调中返回的是Promise, 那么后面then方法的回调会等待它的结束 let promise2 = promise.then(function(value){ console.log('resolved', value) }, function(error){ console.log('rejected', error) }) .then(function(value){ console.log('resolved', value) }, function(error){ console.log('rejected', error) }) .then(function(value){ console.log('resolved', value) }, function(error){ console.log('rejected', error) }) console.log(promise2 === promise) promise.then(function(value){ console.log('resolved', value) }).catch(error => { console.log("error", error) })

Promise 异常处理

Promise实例的catch方法 then方法中的失败回调 区别: (1)then注册失败回调只能捕获到前一个promise的异常 (2)catch是给整个Promise链条注册的失败回调

Promise 静态方法

resolve() reject() Promise 静态方法 Promise.resolve() Promise.reject() 三种是等价的 有thenable接口的函数 Promise.resolve('f00').then( value => { console.log('resolve', value) }) Promise.resolve({ then: (onFulfilled, onRejected) => { onFulfilled('f00') } }).then(value => { console.log(value) }) new Promise((resolve, reject) => { resolve('f00') }).then(value => { console.log('new', value) }) Promise.reject(new Error('rejected')).catch(error => { console.log('error', error) })

Promise 并行执行

all()方法 race()方法

Promise 执行时序 / 宏任务 微任务

微任务: 提高整体的响应能力 Promise 执行时序 / 宏任务 微任务 console.log('global start') setTimeout(()=>{ console.log('setTimeout1') }, 1000) setTimeout(()=>{ console.log('setTimeout') }, 100) Promise.resolve().then(()=>{ console.log('promise') }).then(()=>{ console.log('promise1') }) console.log('global end')

Generator异步方案

//Generator异步方案 function *foo(){ console.log("start") try{ const res = yield 'foo' console.log(res, 'res') }catch(e){ console.log(e, 'e') }

} const generator = foo() const result = generator.next() console.log(result, 'result') generator.next('bar') generator.throw(new Error('Generator Error')) //管理异步流程 体验Generator 函数异步方案 function *main(){ try{ const users = yield promise console.log('users', users)

    const posts = yield Promise.resolve(200)
    console.log(posts, 'posts')
}catch(e){
    console.log(e)
}

} const g = main() const result = g.next() result.value.then(data => { const result2 = g.next(data) if(result2.done) return result2.value.then(data => { g.next(data) }) }) //递归执行Generator函数 const g = main() function handleResult (result){ if(result.done) return result.value.then(data => { handleResult(g.next(data)) }, error => { g.throw(error) }) } handleResult(g.next()) function co(generator){ const g = generator() function handleResult (result){ if(result.done) return result.value.then(data => { handleResult(g.next(data)) }, error => { g.throw(error) }) } handleResult(g.next()) } co(main)

Async/ Await 语法糖 语言层面的异步编程标准

async function mainSync(){ try{ const users = await promise console.log('users', users)

    const posts = await Promise.resolve(200)
    console.log(posts, 'posts')
}catch(e){
    console.log(e)
}

} const mains = mainSync() mains.then(()=>{ console.log('all completed') })