关于这个问题其实我以前没有想过,但就是在最近,我踩坑了,我才明白了这些东西,接下来我就来给大家简单的谈一下。
首先,先来简单介绍一下同步、异步以及回调函数的概念,以此来帮助大家快速的理解问题
- 同步:发出一个调用时,在没有得到结果之前,该调用就不返回;一旦调用返回,就得到返回值。换句话说,就是由调用者主动等待这个调用的结果。
- 异步:调用在发出之后,这个调用就直接返回了,所以没有返回结果。当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知或通过回调函数,让调用者能响应结果。
- 回调函数:主函数通过参数将函数传递到其它代码的,某一块可执行代码的引用。简单点来说就是,一个函数执行完成之后的返回数据,通过参数的形式传递给主函数。
然后进入主菜,说下我当时遇到的问题。
问题描述
js 中有一前一后两个语句,第一个是加载控件,就是显示加载中这个样式动画;第二个是一个异步方法,回调函数中存在一个 alert 弹窗。当我执行的时候,发现了一个问题,就是加载动画总是延迟几秒等待异步方法调用完成才显示加载动画和弹出 alert 弹窗,几乎是同时。这肯定是不符合我的需求的,我最开始的想法就是异步去调用后台接口的时候显示加载动画提示用户等待,而不是调完完成才显示加载动画,那样也就没有了意义。
问题分析
一开始不了解到底是个怎么回事,就很迷茫,起初我以为是代码的问题,后来还是没有任何思绪,就问了别人一下,然后大佬跟我说,js 本身是单线程的,每次只能执行一个任务,我的问题就是加载动画和异步方法执行的太快了,导致加载动画那行代码虽然执行了,但是显示的时候需要跟异步回调 alert 弹窗去竞争CPU资源,正常的话是按照你用一会CPU,我用一会CPU,这就导致了最后两个控件几乎是同时显示出来的,差不多就是这个道理。
问题解决
听完之后感觉瞬间明白了很多东西,然后用了一个setTimeout()函数给异步方法延迟调用了100毫秒,这个问题马上就解决了。
但是随之而来的又出现了一个问题,因为异步函数他其实可以理解为单开一个线程去执行,它执行了之后并不会马上回调,而是等到处理完成之后把结果传给回调函数。异步调用它其实不会影响之前的代码,但是之后的代码如果有回调函数的标志字段,就比如说执行成功,回调函数去更新这个标志字段的值。但是调用异步函数后,会马上去接着向下执行代码。同步和异步都是可以有回调函数的,不过现在一般异步回调用的比较多。同步的话是会等待着这个函数执行真的结束再向下执行,所以下面的标志字段值并不会受到影响。而异步则是执行了函数之后直接向下执行,并不会等待,所以这样的话。我们放在回调中的标志字段就又可能还没有被赋值,下面判断标志字段位的代码其实就是个问题。
其实这种问题有很多解决方案,就比如说可以轮询判断标志位是否已被赋值,已被赋值就可以结束轮询,向下执行;或者就是把下面要执行的操作放在回调里面,执行完成回调里原有的操作后直接执行之后的代码,这样的话就比较方便,不用单独去搞一个轮询判断,这样问题就解决了。
问题就是这么个问题,事情就是这么个事情,又学到了新知识!