JS队列函数和异步执行示例详解
Jul 07, 2017 pm 02:57 PM这篇文章主要为大家详细介绍了JavaScript队列函数和异步执行的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
编辑注:在Review别人的JavaScript代码时曾看到过类似的队列函数,不太理解,原来这个是为了保证函数按顺序调用。读了这篇文章之后,发现还可以用在异步执行等。
假设你有几个函数fn1、fn2和fn3需要按顺序调用,最简单的方式当然是:
1 2 3 |
|
但有时候这些函数是运行时一个个添加进来的,调用的时候并不知道都有些什么函数;这个时候可以预先定义一个数组,添加函数的时候把函数push 进去,需要的时候从数组中按顺序一个个取出来,依次调用:
1 2 3 4 5 6 7 |
|
这样函数有没名字也不重要,直接把匿名函数传进去也可以。来测试一下:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
这个实现目前为止工作正常,但我们忽略了一个情况,就是异步函数的调用。异步是JavaScript 中无法避免的一个话题,这里不打算探讨JavaScript 中有关异步的各种术语和概念,请读者自行查阅(例如某篇著名的评注)。如果你知道下面代码会输出1、3、2,那请继续往下看:
1 2 3 4 5 6 7 |
|
假如stack 队列中有某个函数是类似的异步函数,我们的实现就乱套了:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
问题很明显,fn2确实按顺序调用了,但setTimeout里的function fn2Timeout() { console.log(‘第二个调用') }却不是立即执行的(即使把timeout 设为0);fn2调用之后马上返回,接着执行fn3,fn3执行完了然才真正轮到fn2Timeout。
怎么解决?我们分析下,这里的关键在于fn2Timeout,我们必须等到它真正执行完才调用fn3,理想情况下大概像这样:
1 2 3 4 5 6 |
|
但这样做相当于把原来的fn2Timeout整个拿掉换成一个新函数,再把原来的fn2Timeout和fn3插进去。这种动态改掉原函数的写法有个专门的名词叫Monkey Patch。按我们程序员的口头禅:“做肯定是能做”,但写起来有点拧巴,而且容易把自己绕进去。有没更好的做法?
我们退一步,不强求等fn2Timeout完全执行完才去执行fn3,而是在fn2Timeout函数体的最后一行去调用:
1 2 3 4 5 6 |
|
这样看起来好了点,不过定义fn2的时候都还没有fn3,这fn3哪来的?
还有一个问题,fn2里既然要调用fn3,那我们就不能通过stack.forEach去调用fn3了,否则fn3会重复调用两次。
我们不能把fn3写死在fn2里。相反,我们只需要在fn2Timeout末尾里找出stack中fn2的下一个函数,再调用:
1 2 3 4 5 6 |
|
这个next函数负责找出stack 中的下一个函数并执行。我们现在来实现next:
1 2 3 4 5 6 7 |
|
next通过stack[index]去获取stack中的函数,每调用next一次index会加1,从而达到取出下一个函数的目的。
next这样使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
现在stack.forEach一行已经删掉了,我们自行调用一次next,next会找出stack中的第一个函数fn1执行,fn1 里调用next,去找出下一个函数fn2并执行,fn2里再调用next,依此类推。
每一个函数里都必须调用next,如果某个函数里不写,执行完该函数后程序就会直接结束,没有任何机制继续。
了解了函数队列的这个实现后,你应该可以解决下面这道面试题了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Node.js 中大名鼎鼎的connect框架正是这样实现中间件队列的。有兴趣可以去看看它的源码或者这篇解读《何为 connect 中间件》。
细心的你可能看出来,这个next暂时只能放在函数的末尾,如果放在中间,原来的问题还会出现:
1 2 3 4 5 |
|
redux 和koa 通过不同的实现,可以让next放在函数中间,执行完后面的函数再折回来执行next下面的代码,非常巧妙。有空再写写。
Atas ialah kandungan terperinci JS队列函数和异步执行示例详解. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Artikel Panas

Alat panas Tag

Artikel Panas

Tag artikel panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Bagaimana untuk melaksanakan sistem pengecaman pertuturan dalam talian menggunakan WebSocket dan JavaScript

WebSocket dan JavaScript: teknologi utama untuk melaksanakan sistem pemantauan masa nyata

Spesifikasi dan contoh lekukan bahasa Go

Fungsi Oracle DECODE penjelasan terperinci dan contoh penggunaan

Cara menggunakan JavaScript dan WebSocket untuk melaksanakan sistem pesanan dalam talian masa nyata

JavaScript dan WebSocket: Membina sistem ramalan cuaca masa nyata yang cekap

Tutorial JavaScript Mudah: Cara Mendapatkan Kod Status HTTP

Bagaimana untuk menulis kod PHP dalam penyemak imbas dan mengekalkan kod daripada dilaksanakan?
