JavaScript 是一门单线程语言,也就是说所有的任务都在同一个线程上运行。这就意味着如果某个任务耗时较长,会阻塞其他任务的执行,从而导致页面卡顿或者崩溃。为了解决这个问题,JavaScript 引入了异步执行机制。
异步 JavaScript 执行机制
异步 JavaScript 执行机制是通过事件循环机制来实现的。它的基本原理可以用下图来说明:
-------------------- ------------- -- - ------------------------- -- -- ------------------------- -- - ---------------------- -- ------------------
在这段代码中,首先打印出 'start' 和 'end',然后执行 promise 和 setTimeout 的回调函数。在事件循环机制中,每个任务都被封装为一个任务队列中的事件。事件循环不断地从任务队列中取出事件并执行,执行完一个事件后再去取下一个事件。其中,任务队列分为两种:宏任务和微任务。
宏任务和微任务
宏任务(macro-task)包括整体代码 script、setTimeout、setInterval、setImmediate、I/O 操作等,可以理解为每次执行栈中执行的代码就是一个宏任务(始终只有一个宏任务在执行)。
而微任务(micro-task)则包括 process.nextTick、Promise、Object.observe(已废弃)、MutationObserver(HTML5 新特性)等,每次有异步任务执行完毕后,就会将该异步任务产生的所有微任务依次加入到微任务队列中。当宏任务里的同步代码执行完毕后,会立即清空所有的微任务队列,依次执行微任务,直到微任务队列为空为止。
在上面的示例代码中,setTimeOut 是一个宏任务,Promise.resolve().then() 是一个微任务。因此,在同步任务执行完成之后,先执行 Promise 的回调函数,再执行 setTimeout 的回调函数。
return 语句使用注意事项
return 语句是用来从函数中返回某个值,并结束函数的执行。但是,在异步 JavaScript 中,return 语句并不总是可以起到想象中的作用。下面通过一个案例来说明 return 语句的使用注意事项:
-------- ----------- - ----------------------------------------------------- -------------- -- ---------------- ---------- -- - ----------------- ------ ---- -- - ----- ------ - ----------- -------------------
在这段代码中,fetchData 函数发起了一个 HTTP 请求,并通过 Promise 对象返回请求结果。我们在 fetchData 函数中使用了 return 语句来返回请求结果,并将其赋值给变量 result。但是,当我们运行这个代码时,会发现 result 的值为 undefined。这是因为 fetchData 函数并没有直接返回数据,而是采用了异步的方式将数据返回,所以在 fetchData 函数执行完成时,Promise 对象还没有完成。因此,我们需要使用 async/await 或者 Promise.then() 来获取异步函数的返回值。
----- -------- ----------- - ----- -------- - ----- ----------------------------------------------------- ----- ---- - ----- --------------- ----------------- ------ ---- - ----------------------- -- - ------------------- --
在这个修改后的代码中,我们使用了 async/await 关键字来实现异步调用,并通过 .then() 方法来获取异步函数的返回值。这种方式可以确保返回值能够正常传递到回调函数中。
总结
异步 JavaScript 执行机制是为了避免页面卡顿和崩溃
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/27793