这道js的面试题,是这样的,页面上有一个按钮,一个ul,点击按钮的时候,每隔1秒钟向ul的后面追加一个li, 一共追加10个,li的内容从0开始技术( 0, 1, 2, ....9 ),首先我们用闭包封装一个创建li元素的函数.

1         var create = (function(){
2             var count = 0;
3             return function(){
4                 var oLi = document.createElement( "li" );
5                 oLi.innerHTML = count++;
6                 return oLi;
7             }
8         })();

页面上的2个元素:

<input type="button" value="点我">
<ul id="box"></ul>
js代码:

 1 var oBtn = document.querySelector( "input" );2 var oBox = document.querySelector( "#box" );3 4 var create = (function(){5     var count = 0;6     return function(){7         var oLi = document.createElement( "li" );8         oLi.innerHTML = count++;9         return oLi;
10     }
11 })();12
13 oBtn.onclick = function(){
14     setTimeout(function(){
15         oBox.appendChild( create() );
16         setTimeout( function(){
17             oBox.appendChild( create() );
18             setTimeout( function(){
19                 oBox.appendChild( create() );
20             }, 1000 );
21         }, 1000 );
22     }, 1000 );
23 }

点击按钮的时候,用回调函数嵌套方式,这里我加入3个li,就已经快受不了了,这就是javascript著名的回调地狱,那么在这里,我用循环简化一下:

 1 var oBtn = document.querySelector("input");2 var oBox = document.querySelector("#box");3 var timer = oNode =  null;4 var create = (function () {5     var count = 0;6     return function () {7         var oLi = document.createElement("li");8         oLi.innerHTML = count++;9         return oLi;
10     }
11 })();
12 function add(){
13     oNode = oBox.appendChild( create() );
14     if ( oNode.innerHTML < 9 ) {
15         timer = setTimeout( add, 1000 );
16     }else {
17         clearTimeout( timer );
18     }
19 }
20 oBtn.onclick = function () {
21     add();
22 }

恩,确实简化了,但是这种面向过程的方式,耦合性太强,下面呢,我就把这个封装成一个通用队列

第一步:封装一个队列,包含( 入列,出列),队列的特点(先进先出,如果你不懂这个,需要去补下基本的数据结构与算法内容)

1 var Queue = function () {2     this.list = []3 }4 Queue.prototype = {5     constructor: Queue,6     enQueue: function ( fn ) {7         this.list.push( fn );8         return this;9     },
10     deQueue: function () {
11         var fn = this.list.shift() || function () {};
12         fn.apply( this, arguments );
13     }
14 }

我们来使用它:

1 var oQ = new Queue();2 oQ.enQueue( function(){3     console.log( 'ghostwu1' );4 }).enQueue( function(){5     console.log( 'ghostwu2' );6 }).enQueue( function(){7     console.log( 'ghostwu3' );8 }).deQueue();9 while( oQ.list.length ){
10     oQ.deQueue();
11 }

第二步、虽然我们现在实现了一个队列,但是,这玩意是同步的,接下来继续改造成异步的:

 1 var oQ = new Queue();2 oQ.enQueue( function(){3     var _this = this;4     console.log( 'ghostwu1' );5     setTimeout( function(){ _this.deQueue(); }, 1000 );6 }).enQueue( function(){7     var _this = this;8     console.log( 'ghostwu2' );9     setTimeout( function(){ _this.deQueue(); }, 1000 );
10 }).enQueue( function(){
11     var _this = this;
12     console.log( 'ghostwu3' );
13     setTimeout( function(){ _this.deQueue(); }, 1000 );
14 }).deQueue();
第三步、这样就实现了一个异步队列, 这里有个小东西要注意下,把this保存下来,因为定时器的this指向的是window.另外在封装deQueue(出列)函数时,一定要给个空函数,否则出列完了之后,会报错,但是这玩意还是有耦合性,继续改造:1 <input type="button" value="点我">2 <ul id="box"></ul>3 <script>4 var Utils = {5     isFunction: function (a) {6         return Object.prototype.toString.call(a) === '[object Function]';7     },8     isNumber: function (a) {9         return typeof a === 'number';
10     }
11 };
12 var Queue = function () {
13     this.list = []
14 }
15 Queue.prototype = {
16     constructor: Queue,
17     enQueue: function (fn) {
18         this.list.push(fn);
19         return this;
20     },
21     delay: function (time) {
22         this.list.push(time);
23         return this;
24     },
25     deQueue: function () {
26         var _this = this;
27         var cur = this.list.shift() || function () { };
28         if (Utils.isFunction(cur)) {
29             cur.apply(_this, arguments);
30             if (_this.list.length) _this.deQueue();
31         } else if (Utils.isNumber(cur)) {
32             setTimeout(function () {
33                 _this.deQueue();
34             }, cur);
35         }
36     }
37 }
38
39 var oBtn = document.querySelector("input");
40 var oBox = document.querySelector("#box");
41 var create = (function () {
42     var count = 0;
43     return function () {
44         var oLi = document.createElement("li");
45         oLi.innerHTML = count++;
46         return oLi;
47     }
48 })();
49 oBtn.onclick = function () {
50     var oQ = new Queue();
51     function add() {
52         for (var i = 0; i < 10; i++) {
53             oQ.enQueue(function () {
54                 oBox.appendChild(create());
55             }).delay(1000);
56         }
57     }
58     add();
59     oQ.deQueue();
60 }
61 </script>

这样封装之后,我们的异步队列就变得通用一点了,把延时和业务逻辑分开处理

[js高手之路]javascript腾讯面试题学习封装一个简易的异步队列相关推荐

  1. HTML弧度文本,[js高手之路] html5 canvas系列教程 - 文本样式(strokeText,fillText,measureText,textAlign,textBaseline)...

    canvas提供两种输出文本的方式: strokeText:描边文本 fillText:填充文本 fillStyle配合fillText使用,strokeStyle配合strokeText使用 str ...

  2. [js高手之路]设计模式系列课程-发布者,订阅者重构购物车

    发布者订阅者模式,是一种很常见的模式,比如: 一.买卖房子 生活中的买房,卖房,中介就构成了一个发布订阅者模式,买房的人,一般需要的是房源,价格,使用面积等信息,他充当了订阅者的角色 中介拿到卖主的房 ...

  3. [js高手之路]从原型链开始图解继承到组合继承的产生

    于javascript原型链的层层递进查找规则,以及原型对象(prototype)的共享特性,实现继承是非常简单的事情 一.把父类的实例对象赋给子类的原型对象(prototype),可以实现继承 1 ...

  4. [js高手之路]原型对象(prototype)与原型链相关属性与方法详解

    一,instanceof: instanceof检测左侧的__proto__原型链上,是否存在右侧的prototype原型. 我在之前的两篇文章 [js高手之路]构造函数的基本特性与优缺点 [js高手 ...

  5. [js高手之路] html5 canvas系列教程 - 掌握画直线图形的常用API

    我们接着上文[js高手之路] html5 canvas系列教程 - 认识canvas以及基本使用方法继续. 一.直线的绘制 cxt.moveTo( x1, y1 ): 将画笔移动到x1, y1这个点 ...

  6. 前端画圆弧html弧线的像素,[js高手之路] html5 canvas系列教程 - arc绘制曲线图形(曲线,弧线,圆形)...

    arc:画弧度 cxt.arc( x, y, 半径, 开始角度,结束角度,是否逆时针 ); x, y: 为弧度的中心横坐标和纵坐标,如果这是画一个圆.那么x,y就是圆的圆心. 开始角度与结束角度都是以 ...

  7. [js高手之路]打造通用的匀速运动框架

    本文,是接着上文[js高手之路]匀速运动与实例实战(侧边栏,淡入淡出)继续的,在这篇文章的最后,我们做了2个小实例:侧边栏与改变透明度的淡入淡出效果,本文我们把上文的animate函数,继续改造,让他 ...

  8. [js高手之路]深入浅出webpack教程系列9-打包图片(file-loader)用法

    [js高手之路]深入浅出webpack教程系列索引目录: [js高手之路]深入浅出webpack教程系列1-安装与基本打包用法和命令参数 [js高手之路]深入浅出webpack教程系列2-配置文件we ...

  9. [js高手之路] html5 canvas系列教程 - 线条样式(lineWidth,lineCap,lineJoin,setLineDash)

    上文,写完弧度与贝塞尔曲线[js高手之路] html5 canvas系列教程 - arcTo(弧度与二次,三次贝塞尔曲线以及在线工具),本文主要是关于线条的样式设置 lineWidth: 设置线条的宽 ...

最新文章

  1. 一款由css3和jquery实现的响应式设计导航
  2. 目标检测——Faster R_CNN使用smooth L1作为bbox的回归损失函数原因
  3. 移动客户端与服务器端安全通信方案
  4. 每日一天:对象数组去重
  5. python3.0什么时候发布的_Django 3.0 发布说明
  6. 计算机硬件知识考证题,计算机硬件知识题(答案)资料
  7. 计算机代码图表,微信小程序图表插件(wx-charts)实例代码
  8. Uber开源深度概率编程语言Pyro,AI实验室蛰伏一年首现身
  9. SQLite学习笔记
  10. 【密码学】基于 SM3 算法的 HMAC 快速实现
  11. hive sql 添加字段以及修改字段
  12. python存钱程序_Python基础(六) 52周存钱demo
  13. MySQL的函数——聚合函数、数学函数、字符串函数、日期函数
  14. 接口01_精通Postman接口测试基础应用
  15. sql重复数据只取一条记录
  16. Qt读取qss文件失败或qss不生效解决方案
  17. msf永恒之蓝漏洞复现及问题解决
  18. 酒店计算机管理系统维护合同,酒店计算机管理系统维护合同.pdf
  19. 【Android数据存储】ContentProvider详细介绍(附实例源码)
  20. rtmp over quic直播服务--mediago

热门文章

  1. bitherj java_比太钱包为什么从 Bitcoinj 切换到了 Bitherj ?比太钱包从 Bitcoinj 切换到了 Bitherj原因是什么?...
  2. 三角形旋转c语言程序,c语言图形,请高手修改,效果是一个三角形绕一点旋转一周...
  3. 华为p50 pro 鸿蒙,华为P50Pro确认!1英寸大底相机+首发鸿蒙:这才是华为最强实力...
  4. C++ 偏微分数值计算库_一文带你了解计算流体力学CFD及其应用领域
  5. java string is empty_从源码分析java.lang.String.isEmpty()
  6. 培养杰出程序员的捷径
  7. 二级VB培训笔记08:公共基础知识
  8. akka案例:统计单词个数
  9. CTSC2017APIO2017
  10. 向量的大小和方向,零向量的方向_3