异步调用在JavaScript中的执行过程及期原理:

调用栈 Call stack,是正在执行的工作表
消息队列 Queue,就是待办的工作表
setTimeout是异步调用,Web APIs会为它执行其内部api的动作
同步或异步:运行环境提供的API是以同步还是异步模式的方式工作
同步模式API:当前任务执行完,才会往下执行,比如console.log
异步模式API:下达任务开启的指令,就会继续往下执行,代码不会在这一行等待结束,比如setTimeout
回调函数,放在函数当中,异步任务完成即会调用,想要做的事情
Promise
Promise 对象的then方法会返回一个全新的Promise对象
后面的then方法就是在为上一个then返回的Promise注册回调
前面then方法中回调函数的返回值会作为后面then方法回调的参数
如果回调中返回的是Promise,那后面then方法的回调会等待它的结束 ```javascript // 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) {
} else {resolve(this.response)
} } xhr.send() }) }reject(new Error(this.statusText))
//ajax(‘/api/users11.json’) //.then(function onFulfilled (value) { // console.log(‘onFulfilled’, value) //}, function onRejected (error) { // console.log(‘onRejected’, error) //})
//使用 catch 注册失败回调是更常见的
ajax(‘/api/users11.json’) .then(function onFulfilled (value) { console.log(‘onFulfilled’, value) }) .catch(function onRejected (error) { console.log(‘onRejected’, error) })
- <br />Promise 并行执行- <br />Promise.all()- <br />多个请求,同时调用,全部返回结果,才结束```javascriptajax('/api/urls.json').then(value => {const urls = Object.values(value)const tasks = urls.map(url => ajax(url))return Promise.all(tasks)}).then(values => {console.log(values)})
- Promise.race()- 也能合并执行,但是只会等待第一个任务结束,就会完成Promise对象
Promise的回调会作为微任务执行,会在本轮调用结束的末尾自动执行
setTimeout是宏任务,在队伍末尾
目前绝大多数异步调用都是作为宏任务执行
Promise MutationBoserver process.nextTick 是微任务
Generator 生成器函数 ```javascript // 生成器函数回顾 function * foo () { console.log(‘start’)try {
const res = yield 'foo'console.log(res)
} catch (e) {
console.log(e)
} } //此处得到一个生成器对象 const generator = foo()
const result = generator.next() //这里next()会一直执行到上面yield关键词的位置,把yield后面这个值,返回出去 //然后foo函数暂停下来,值用为foo的value返回,同时生成器里有一个done属性,表示是否完成构造函数 console.log(result) //所以此处打印: { value: “foo” , done: false}
// generator.next(‘bar’) //这里再一次调用next的话,就会从yield往下执行到结束,或者到下一个yield的位置
generator.throw(new Error(‘Generator error’)) //throw方法也会让生成器函数继续往下执行,但会抛出一个异常 // Error: Generator error
- generator 异步方案```javascript// Generator 配合 Promise 的异步方案function ajax (url) {return new Promise((resolve, reject) => {var xhr = new XMLHttpRequest()xhr.open('GET', url)xhr.responseType = 'json'xhr.onload = () => {if (xhr.status === 200) {resolve(xhr.response)} else {reject(new Error(xhr.statusText))}}xhr.send()})}function * main () {try {const users = yield ajax('/api/users.json')console.log(users)const posts = yield ajax('/api/posts.json')console.log(posts)const urls = yield ajax('/api/urls11.json')console.log(urls)} catch (e) {console.log(e)}}const g = main()const result = g.next()//这里value就会是第一个yield位置返回的值,然后通过then的方式去指定Promise的回调result.value.then(data => {//第一个拿到的结果作为参数传给g,继续执行,const result2 = g.next(data)//这样就近乎于避免了promise的回调,有一种同步代码的体验if (result2.done) return//如果有第二个请求就按第一个一样调用.then方法result2.value.then(data => {const result3 = g.next(data)if (result3.done) return//当done为true时,就会结束result3.value.then(data => {g.next(data)})})})//用递归优化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 await
语言层面的异步编程标准 ```javascript //上面简化 // await关键词,只能出现在async函数内部 async function main () { try { const users = await ajax(‘/api/users.json’) console.log(users)
const posts = await ajax(‘/api/posts.json’) console.log(posts)
const urls = await ajax(‘/api/urls.json’) console.log(urls) } catch (e) { console.log(e) } } //不需要co生成器了 //main ()
//还可以返回一个promise对象,以便于对整体代码进行控制 const promise = main()
promise.then(() => { console.log(‘all completed’) }) ```
