一,正常情况下同步代码
通常情况下,我们的代码执行顺序是从上到下,按照顺序执行。
console.log('1'); const a = test(); console.log(a); function test() {
console.log('2'); return '函数返回'; } console.log('3');
这个代码片段的返回结果是:
1,2,函数返回,3
二,有异步的代码执行情况
console.log('1'); const a = test(); console.log(a); function test() {
setTimeout(() => {
//setTimeout是异步操作 console.log('2'); return '函数返回'; }, 1000); } console.log('3');
这个代码片段的执行结果便是:
1,undefined,3,2
三,总结原因-同步阻塞与异步非阻塞
因为js是单线程机制的,所有的操作都必须一个一个来,如果中间有一个操作非常耗时,那整个线程都会阻塞在那里,这就是同步阻塞。
为了解决这个问题,js引入了事件和回调函数机制,对于一个IO操作,比如一个ajax,当发出一个异步请求后,程序不会阻塞在那里等待结果的返回,而是继续执行下面的代码。当请求成功获取到结果后,就会调用回调函数来处理后面的事情,这个就是异步非阻塞。
具体这个概念可以看我之前的文章:js中的同步与异步的理解
对应于一中正常的代码,就是同步阻塞,等一行代码执行完毕后才能执行下一行代码。 对应于二中的异步的代码,就是异步非阻塞,发现是异步后,不会阻塞住,而是继续执行后续的代码,等异步结果出来后,再执行。
四,回调函数的产生和应用
有时候,我们需要在异步操作后再进行某些操作。于是可以在异步操作后再调用一个函数,利用的就是异步操作结果出来后,其内部代码顺序执行的原理:
console.log('1'); test(callback); function test(cb) {
setTimeout(() => {
//setTimeout是异步操作 const a = 2; cb(a); }, 1000); } function callback(val) {
console.log('回调函数执行', val); } console.log('3'); 执行结果:1,3,回调函数执行2
如果第一个异步API执行的结果,需要给第二个异步api作为参数使用。但是第二个异步api在第一个异步api还没有执行完毕返回结果就执行了,那怎么办?
function asyncFn1(cb) {
setTimeout(() => {
console.log('这是第一个异步操作'); const a = 1; cb(a); }, 1000); } function asyncFn2(val) {
setTimeout(() => {
console.log('这是第二个异步操作', val); }, 2000); } asyncFn1(asyncFn2);
五,promise的使用
引入promise的最大作用,就是把异步操作的过程和结果做到了分离,可以用promise.then()来获取和处理异步操作的结果。
function asyncFn1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('这是第一个异步操作', 222); const a = 1; resolve(a); }, 1000); }); } function asyncFn2(val) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('这是第二个异步操作', val); resolve(); }, 2000); }); } console.log('1111'); asyncFn1().then(res => {
asyncFn2(res); }); console.log('3333');
打印的结果将会是:
1111 3333 这是第一个异步操作 222 这是第二个异步操作 1
可以参考这张图理解:
主线程按顺序执行代码
1,执行console.log('1111'); 2,执行asyncFn1,遇到setTimeout发现是异步,注册一下 3,执行console.log('3333')(因为js是异步非阻塞,所以这里继续执行后面的代码) 4,第一个异步setTimeout执行完毕了, console.log('这是第一个异步操作', 222); 5,因为使用了promise,所以会等第一个异步执行完毕,才开始执行then中的第二个异步
主要就是理解这句话,js是异步非阻塞的,同步执行,异步注册后等待执行完毕。promise可以将回调函数的处理转化成链式调用,做到异步操作和结果的分离。
需要注意的是,promise并不会产生阻塞效果,它只对它包裹的异步操作负责,只能够实现它包裹的异步操作执行完毕后,才会执行.then中的代码。所以这里console.log(‘3333’)会先执行。
换句话说,promise只是局部的,受用户控制的顺序执行,采用的方案是promise包裹异步操作,resolve()返回异步结果,然后.then中处理异步结果。
六,async和await
async和await就更进一步,它能够将promise中的异步转化为同步,也就是说,它能产生阻塞效果,等待它后面的代码执行完毕后才会继续往下执行。
值得注意的是,await后面必须是一个promise对象才可以。
function asyncFn1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('这是第一个异步操作', 222); const a = 1; resolve(a); }, 1000); }); } function asyncFn2(val) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('这是第二个异步操作', val); resolve(); }, 2000); }); } console.log('1111'); const result = await asyncFn1(); await asyncFn2(result); console.log('3333');
执行的结果:
1111 这是第一个异步操作 222 这是第二个异步操作 1 3333
到此这篇js中的同步与异步的理解的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/qdvuejs/11041.html