00:00
下面我们要去看一个东西,看怎么样去说明GS是单线程执行的。啊,尤其是一些回调函数啊,因为回调函数是我们调的嘛,不是所以吧,我就把握不准,到底是在当前我的主线执行呢,还是在分线执行,就给人的感觉吧,就是在分线执行似的。啊,甚至有很多同学觉得他就是在分线执行。啊,我们现在就要验证一下GS是单线程执行的啊来。啊,这个里面呢,我我去我去写写几个啊,就以time为例啊,呃,先搞一个2000。可以吧,哪一个这个是TIMEOUT2吧,啊写个它好再来一个。
01:02
这是一个太帽的什么呢,一。可以吧,好可以啊,接着来这一个假设啊,这里面我来一个吧,我来一个函数来个FN啊,来一个打印输出FN啊,我就去调用这个FN可以吧,可以好,那这个地方我们执行的顺序应该怎么样打印顺序。先输出FN,接着输出一接着才输是什么啊。这个应该能看懂吧,嗯,这个应该能懂。啊,没什么太大问题啊。是吧,好,下面我要做件事情,做些什么事,我来个。我来个alert,大家看啊,Alert有一个什么特点,是不是它会去暂停程序的执行,是不是来打卡啊,我来打印输出一下,这个是叫alert之前是吧。
02:17
啊,下面我再来去再来去写一个啊,再在下面写一个answer.log啊,这个就是什么alert之后,好,那我问大家,请问打印的是一个什么样感觉。就打印顺序是什么样的顺序,先执行FN,接着执行它。接着了是不是弹一个宽出来,弹宽了之后,弹宽的时候,这个字行没有没有没有没有。啊,来看一下啊轴,看看我这两个输出是不是很快就输出完了,那接着是不是我的这个糖框出来了吧,那出来以后我们说勒的作用是什么。
03:09
来说一下叫暂停当前主线程的执行是吧?好,那我这个停了有一会了吧,那我问大家我一点确认会是什么样的情景。我觉得好使。得了之后会立马执行吗?关键我就问大家这些呢。他们会怎么样呢?也就说他们是立即执行呢,还是说要过一会才执行。为啥过一会我就觉得不好理解啊,你你咋要过一会儿,我我都我都等了多久了,我不说不说两三秒,至少很长很长时间了,远远超过两秒钟了,对不对。
04:02
是这意思吧,我现在远远超过两个,都停了这么久了,我都跟大家说了这么多话了。啊,但是呢,看一下轴。什么意思啊,而乐他除了暂停这个当前主线程执行,他还暂停了什么那个计时。你说计时停了没有,停了,他要没停的话,你想我一点确认,他是立马要出来。那么理解啊,暂停计时。那什么时候才恢复呀?点击确定后什么是不是恢复,懂不懂,一个是恢复程序的执行同和什么计时啊,你是计时是不是开始继续往下计时啊,能不能理解啊,OK,好,那我问大家,大家看看啊。
05:17
这个里面啊,还有一个事情,我在这个地方打一个A了,那你想这又会怎么样呢?先会弹出一个乐减减减是吧,接着我点击确定,确定以后怎么办,是个什么情节,过了几秒钟。啊,过了两秒啊,这个这个就两秒没没意思了。那一早已经执行了是吧。来再刷一下啊,我再来刷一下,把这些都先去掉啊。
06:01
把这些都先去掉,我再算一下来看啊,点下它过了一秒以后,是不是执行我的我的那个定时器,一秒的定时器,它是不是又弹出一个了。看它一秒以后弹出,那我我点确定以后呢。再过多长时间,多长时间是一秒还是两秒几秒一秒啊,因为刚才不统计过疫秒了吗?但实际上你看诶,我对打没看是打印输出是吧,没注意啊,我就一直等着那个乐的出来,我说半天怎么不出来。这样的吧,嗯,来我们再来看一遍啊,把这个流程大家要看清楚它的,首先是它啊,点了它以后一秒以后是不是出来一个接着呢。
07:06
是吧,啊大概是这样子,好大家现啊看着你说这个时候我们能不能看出来这些这一些东西,这包括这些回调函数,这个定时机的回收,实际上都是在主线上执行的,因为我们alert的时候停暂停的是当前的什么主线程。啊,暂停的是当前的主线程,而最终他们啊,他们其实也是在主线程去运行,它一暂停的话,后面的事情就不会再继续的进行了,包括最后我们发现,其实后来我才发现。啊,我开始也以为这个我一点这个回答来说就应该马上执行,因为时间过去了很久了嘛,但后来才发现,其实他同时也暂停了什么,暂停了计时这样一个操作。
08:04
但是到现在为止,其实并没有去看出来它内部到底是怎么运行的,说实话,因为我们还没有去讲到它内部怎么运行,要说到这个,那我们就得去做一些事情。要进行代码进行分类了,那以前我们好像做过代码分类,我们分为什么全局代码和什么函数局代码,对不对?那这一次我们又有代码分类了,所以这一次我们怎么分呢?我们把它分为初始化代码。和什么呢?回调代码,那我问大家啊,你说这个里面哪些是回调代码,是回调函数里面的代码,就是什么呢?回调代码,那你说这个set time out。这个是什么代码?这代out这条语句,这不是条语句吗?什么代码?你不要跟我说全局代码,我们现在都不是搞的全局代码,我们说的是初始化代码和回调代码这两类,对不对?
09:13
这个set out什么代码?初始化代码,只是这个初始化代码里面是不是指定了一个定时器的回调函数,它里面相当于是包含了一个回调代码,这个代码能够立即得到执行吗?来看这里我要写一个非常重要的一句话,看啊。啊,不是的,我再加个定时器。我这一次我写我写零。我请问呐,你说这个零是什么时候执行呢?看到啊,也就是说什么意思,这个零这一条语句输出和这条语句输出谁先是上面的先还是下面的先,嗯,这就有意思了,是吧,到底是这个alert这个先输出,还是这个太零先输出。
10:21
来,我们来看一下。是不alert呀,那问了呀,是alert之后,我们不还有一个at之后和这个你吗?那我希望谁先输出A乐之后。你看这个泰曼尼是马上就输出啊,就解级了,看懂吧,但是他必须等到什么时候才会去输出了,这个太胖的尼是吧,OK,这个地方这个分类很重要。这个分类很重要,我们把那个代码分为初始化代码和回调代码,那个引擎它是不是执行的流程早已确定好了,他的流程是个什么样的流程呢?非常简单,先执行初始化代码,无论初始化代码执行多长时间,他都要先保证把初始化代码执行完,初始化代码有没有可能执行很长时间,有没有可能有刚才我们不搞个很长的后循环吗?
11:35
是吧,先必须保证初始化代码执行完了以后,后面在某一个时刻才去执行什么毁掉代码,可能是立即执行,也可能是要等一会才执行,就回调代码,是一定是我们初始化代码执行完就立即执行回调代码吗?是吗?一定不一定。
12:00
啊。首先得保证他们之后才执行答案,但是并不能保证立即就执行我们的这个毁掉代码,毁掉代码得在某一个时刻,譬如说举个例子,我们的这两个。是不是就是初始化代码执行完了以后,还要过一会才执行,对不对对的,但是他呢,是不是立即就执行了,是不是啊,因为它零嘛,但零是代表我的这个函数马上执行吗?不是也要等到什么初始化代码执行完了以后。这是他的固定的一个逻辑,这个逻辑会变吗?不会变。而在执行初始化代码的时候,它可能也有这样的代码,就这种代码是一般的代码,还有一些代码可以说设置定时器有没有可能有吧,这种设置定时器本身它是什么代码,初始化代码,但是它里面是不是包含了一些回的函数?
13:10
我设定设置这个定时器的时候,我的定回函数执不执行不执行,这个强调一个好,也有可能去绑定事件监听。有可能吧,我绑定事界监听那个回调函数,执不执行,不执行,什么时候才执行呢?事件触发的时候是不是才执行。能不能懂啊好,还有一个这个呢,大家还没学啊,后面我们会讲啊,先以这两个来说明这个问题。而这一些他们是不是都对应一些回调函数啊,对吧,都对应一个回调函数啊,这个回调函数我们平常会说什么呢?叫异步执行。
14:06
何为义不之行啊?是吧,其实非常简单,就是某些代码,某些东西必须在所有的初始化代码执行以后才有可能被得到,执行这样的代码,我们就把它称为什么呢?异步的代码。你想想看,你这个这个是非常明确的,就我们虽然说设置的定时的时间,是不是定时时间零呢。零代表他马上执行吗?不代表。为什么?因为这些我们这一个函数的调用,它是异步调用了,这里面的代码是异步执行的,什么叫异步执行?非常简单,就只有当我们全这个初始沃代码全部执行完了以后。
15:00
他才有可能得到执行,这里面说的是有可能得到执行,并不是利益,对吧,得看你的时间,得看你是什么类型。啊,这个大家应该要能够去给它搞清楚,大概能懂吧,啊就是这里面首先代码分类,这个大家应该能看懂啊,你要区看哪些是出错代码,哪些是。啊,回调代码这些是出来,这个大家应该能看懂是吧,包括这些是不是都是初始化代码,其实很简单,什么叫回调代码,什么回调函数包含代码,这不很简单一个什吗?什么是回调函数,这个前面说过吧,说过的。嗯,所以判断起来并不难了啊,最后再跟大家说一个事情啊,大家看到啊,为什么GS要设计成单线程模式,而不形成多线程模式了。
16:01
对吧,啊,这个也是需要大家去考去考虑的一个问题,我举个例子大家就明白了啊,假设这里有一个页面,有个界面,里面呢有一个标签是P,标签里面呢有一个文本啊,假设叫叉叉叉吧,随便啊。随便这是一个P标签,那P标签好,P标签是不是对应一个,在内层里面对应一个P标签对象,我们叫P对象,好吧,假设我们现在啊,有两个线程,有两个线程。可以执行,可以有多个线程去更新这个去操作这个P,好一个线程一,一个线程二,我们俩呢,都拿到了这个P。是不是都能看到这个P吧,能不能能当然能看到,都能看到这个P啊,一个线程一,一个线差好线程一准备干嘛呢?准备去更新这个P里面的文本啊,它做更新,而这下面的线程二呢?准备干嘛呢?准备去删除这个P标签。
17:14
能不能懂啊,一个是准备去更新它的文本,一个是去删除,那我们假设啊,现在是多个线程都可以去更新这个界面,那你想啊,有一种极端情况,什么极端情况呢?我们先都看到P了是吧?啊好,都看到P了,在我准备线程二准备去删除这个P的时候,在刚好在这个点,我们说有一个概念叫线程切换,还记得吧,就是就是我们处理器啊,不再去运行这个线场,而运行什么呢?线程一线啊,说错了,反了啊,这一下子就反了,因为反的话就不能说明这个问题了。
18:01
OK,好,再来一下啊,一个是一,一个是二,这个一呢是做更新,二呢做删除。好,开始了,咱俩都看到了P,现在呢,时间是交给P去运行。啊,P运行P啊,交给这个一运行一看到P准备去更新啊,记住啊,他准备去更新,但有没有可能就在这个时间点,那个时间交给了什么?交给RR干嘛去啊?是不是去删除啊,是不是二去删除,那删完了以后接着交给谁运行是不是交给一运行一还会去判判断这个P吧?还会去判断这个P存不存在吗?刚才判断过了吧。能不能懂,刚才已经判断过了,那个程序是不是继续往下执行,他干嘛去,他是不是进行下一步操作更新,那现在能更新吗?能不能不能。
19:12
现在是不能更新了,那因为我的这个P已经没了,你怎么更新呢。是不是报错呀,那也就是说如果我们是多线程的,我们是多线程的是可以同时去操作这个界面的,是有问题的。你说老师这个问题能不能避免?大家说能不能想办法避免,其实是可以避免的,但是只是我们这个操作就比较麻烦了,可以说我举个例子,我只允许允许什么呢?在同一个时刻,譬如说假设我某一个线程去操作P的时候啊,去操作去,我就不允许别的线程再去碰它。
20:02
能不懂就说白了,就是一旦我超P啊,一旦我超有一个线程超到P了,譬如说我这个上面的这个线程一怎么不更新器吗?那我就去做整体,它是一个整体。它是一个整体,我必须把这个执行完了以后才能执行别的。能不能懂,就是我要把整个操作全部执行完才有机会去甄别的,但是我要做到这一点特别麻烦,我要实现这样一个效果特别特别麻烦,但是如果我们换一种方式,我们只有单线程的。只有一个线程能更新这个界面,还有没有这个问题?是不是没有啊,也说即使我有了分线程,我也不允许分线程去干这个事情,甚至于说我分线都没有,可不可以,可以吧?那如果我是单线程,有没有干才的问题,有吗?有还是没有啊,没有啊,我的我的程序是哐哐哐的这种从上往下执行的是吧?先执行初始化代码,接着执行什码毁掉代码,毁掉代码能同时执行吗?为有两个回调都设置为零。
21:21
能不能同时执行,不能,也只能什么一个接一个的执行。必须有先后顺序。啊,把这个稍微理解一下啊,嗯。OK,大家记住,我们的这种方式决定了我们GS只能是单线程的,这一个单线程啊,只说的是什么啊,只能有一个线程能够更新我的什么呢?界面啊界面在以前我们确实GS里面真正只有一个线程,那我们刚才说过了,H5里面是不是可以有多个线程的,对吧?但是即使有了H5那个多个线程的语法也并不能改变一个事实,哪个事实呢?只能有一个线程去更新操作我的什么界面。
22:18
不然的话,我的这个代码的复杂度就会增加很多。这个地方大家应该要有一个基本的一个理解,嗯,但重点还是回到我们前面说的这这个分类和这个监视引擎执行的基本流程。啊,这个呢,大家做一个了解啊,做个了解啊,OK,好,代码呢倒是没什么,都是一些测试性的代码。
我来说两句