详解JavaScript之分解任务

开发 前端
我们都知道,复杂的任务分解成一系列的子任务之后,就变得不是很复杂了。javascript中也存在这种任务分解,本文详细的介绍JavaScript中的分解任务,希望对你有帮助,一起来看。

下面来看,JavaScript分解任务,供参考。

我们通常将一个任务分解成一系列子任务。如果一个函数运行时间太长,那么查看它是否可以分解成一系列能够短时间完成的较小的函数。可将一行代码简单地看作一个原子任务,多行代码组合在一起构成一个独立任务。某些函数可基于函数调用进行拆分。例如:

  1. function saveDocument(id){  
  2. openDocument(id)  
  3. writeText(id);  
  4. closeDocument(id);  
  5. updateUI(id);  

如果函数运行时间太长,它可以拆分成一系列更小的步骤,把独立方法放在定时器中调用。你可以将每个函数都放入一个数组,然后使用前一节中提到的数组处理模式:

  1. function saveDocument(id){  
  2. var tasks = [openDocument, writeText, closeDocument, updateUI];  
  3. setTimeout(function(){  
  4. var task = tasks.shift();  
  5. task(id);  
  6. if (tasks.length > 0){  
  7. setTimeout(arguments.callee, 25);  
  8. }  
  9. }, 25);  

这个版本将每个方法放入任务数组,然后在每个定时器中调用一个方法。从根本上说,现在它成为数组处理模式,只有一点不同:处理函数就包含在数组项中。正如前面一节所讨论的,此模式也可封装重用:

  1. function multistep(steps, args, callback){  
  2. var tasks = steps.concat();  
  3. setTimeout(function(){  
  4. var task = tasks.shift();  
  5. task.apply(null, args || []);  
  6. if (tasks.length > 0){  
  7. setTimeout(arguments.callee, 25);  
  8. else {  
  9. callback();  
  10. }  
  11. }, 25);  

multistep()函数接收三个参数:用于执行的函数数组,为每个函数提供参数的参数数组,当处理结束时调用的回调函数。函数用法如下:

  1. function saveDocument(id){  
  2. var tasks = [openDocument, writeText, closeDocument, updateUI];  
  3. multistep(tasks, [id], function(){  
  4. alert("Save completed!");  
  5. });  

注意传给multistep()的第二个参数必须是数组,它创建时只包含一个id。正如数组处理那样,使用此函数的前提条件是:任务可以异步处理而不影响用户体验或导致依赖代码出错。

(一)限时运行代码

有时每次只执行一个任务效率不高。考虑这样一种情况:处理一个拥有1'000个项的数组,每处理一个项需要1毫秒。如果每个定时器中处理一个项,在两次处理之间间隔25毫秒,那么处理此数组的总时间是(25 + 1) × 1'000 = 26'000 秒,也就是26 秒。如果每批处理50个,每批之间间隔25毫秒会怎么样呢?整个处理过程变成(1'000 / 50) × 25 + 1'000 = 1'500毫秒,也就是1.5秒,而且用户也不会察觉界面阻塞,因为最长的脚本运行只持续了50毫秒。通常批量处理比每次处理一个更快。

如果你记住JavaScript可连续运行的最大时间是100毫秒,那么你可以优化先前的模式。我的建议是将这个数字削减一半,不要让任何JavaScript代码持续运行超过50毫秒,只是为了确保代码永远不会影响用户体验。

可通过原生的Date 对象跟踪代码的运行时间。这是大多数JavaScript分析工具所采用的工作方式:

  1. var start = +new Date(),  
  2. stop;  
  3. someLongProcess();  
  4. stop = +new Date();  
  5. if(stop-start < 50){  
  6. alert("Just about right.");  
  7. else {  
  8. alert("Taking too long.");  

 

由于每个新创建的Data 对象以当前系统时间初始化,你可以周期性地创建新Data对象并比较它们的值,以获取代码运行时间。加号(+)将Data 对象转换为一个数字,在后续的数学运算中就不必再转换了。这一技术也可用于优化以前的定时器模板。
processArray()方法通过一个时间检测机制,可在每个定时器中执行多次处理:

  1. function timedProcessArray(items, process, callback){  
  2. var todo = items.concat();  
  3. setTimeout(function(){  
  4. var start = +new Date();  
  5. do {  
  6. process(todo.shift());  
  7. while (todo.length > 0 && (+new Date() – start < 50));  
  8. if (todo.length > 0){  
  9. setTimeout(arguments.callee, 25);  
  10. else {  
  11. callback(items);  
  12. }  
  13. }, 25);  

此函数中添加了一个do-while循环,它在每个数组项处理之后检测时间。定时器函数运行时数组中存放了至少一个项,所以后测试循环比前测试更合理。在Firefox 3中,如果process()是一个空函数,处理一个1'000个项的数组需要38 – 34毫秒;原始的processArray()函数处理同一个数组需要超过25'000毫秒。这就是定时任务的作用,避免将任务分解成过于碎小的片断。

(二)定时器与性能

定时器使你的JavaScript代码整体性能表现出巨大差异,但过度使用它们会对性能产生负面影响。使用定时器序列,同一时间只有一个定时器存在,只有当这个定时器结束时才创建一个新的定时器。以这种方式使用定时器不会带来性能问题。

当多个重复的定时器被同时创建会产生性能问题。因为只有一个UI线程,所有定时器竞争运行时间。Google Mobile的Neil Thomas 将此问题作为测量性能的方法进行研究,针对iPhone和Android上运行的移动Gmail程序。

Thomas发现低频率的重复定时器——间隔在1 秒或1 秒以上——几乎不影响整个网页应用的响应。这种情况下定时器延迟远超过使UI 线程产生瓶颈的值,因此可安全地重复使用。当多个重复定时器使用更高的频率(间隔在100到200毫秒之间),Thomas发现移动Gmail程序明显变慢,反应较差。

Thomas研究的言外之意是,要在你的网页应用中限制高频率重复定时器的数量。同时,Thomas建议创建一个单独的重复定时器,每次执行多个操作。

原文地址: http://www.yiiyaa.net/1223

【编辑推荐】

  1. JavaScript重构 模块划分和命名空间
  2. JavaScript初学者必须注意的七个细节
  3. Javascript中的函数声明和函数表达式
  4. 在服务端合并和压缩JavaScript和CSS文件
  5. 学习Javascript闭包(Closure)
责任编辑:于铁 来源: yiiyaa.net
相关推荐

2020-04-15 09:20:08

数据护栏行为分析数据库安全

2020-09-29 19:20:05

鸿蒙

2020-11-06 12:12:35

HarmonyOS

2009-11-12 16:41:36

路由器产品

2021-11-10 16:10:18

鸿蒙HarmonyOS应用

2021-06-29 20:51:16

大数据框架分桶

2011-08-04 13:38:01

Objective-C C++

2012-02-14 09:45:02

JavaScript

2023-04-06 00:22:19

JavaScrip任务开发

2020-12-29 08:21:03

JavaScript微任务宏任务

2012-06-05 08:59:35

Hadoop架构服务器

2021-01-18 08:24:51

JavaScriptMicrotask微任务

2016-10-11 20:33:17

JavaScriptThisWeb

2014-12-12 10:13:12

JavaScript

2016-09-07 20:43:36

Javascript异步编程

2013-05-08 10:36:07

JavaScriptJS详解JavaScrip

2023-01-03 10:38:04

函数计算技术

2011-03-28 09:23:31

Visual Stud

2024-03-05 09:22:36

2023-03-13 16:08:00

JavaScript数组函数
点赞
收藏

51CTO技术栈公众号