文档章节

前端异步发展

sunshinewyf
 sunshinewyf
发布于 2017/04/23 17:46
字数 1119
阅读 29
收藏 0

异步在前端中的发展历史不是很长,但是发展的速度还是很快的

###什么是异步 所谓异步,简单点说就是在做一件事情的过程中中断去做另外一件事情。js是单线程的,当然也有异步的概念。异步和同步的区别用图示表示如下: 输入图片说明 由图示可以得出,同步过程时:业务二必须等待业务一的请求结果返回之后才可以开始,而异步过程中,在业务一的请求过程中,当前线程可以先去处理业务二,免去了等待过程中的时间浪费。

###为什么要异步 为什么要引入异步的,异步有下面几点优点:

  • cpu利用率高
  • 用户体验更好
  • 性能更高

从上面图示可以看出,在异步过程中,没有等待数据返回的过程,在请求数据的时候,当前线程又去处理其他业务了,这样就提高了cpu的利用率,cpu的性能必定也会提升。其次,在之前的网站中,我们时常要处理ajax请求,一旦采用同步思路,那么在请求数据返回之前,网页都是一片空白而得不到相应,那样会给用户一种相应很慢的感觉,导致用户体验很差。而异步就使得页面在请求数据的空隙也可以渲染页面,大大提升了用户体验。

###异步的发展历程

####callback时代 回调函数是异步发展的起源,最初源自ajax,对于下面的代码,相信每一个FEer都不会感到陌生:

$.ajax('url',function () {
    //do something
})

但是这样的请求一旦嵌套过多,就会出现下面的callbacks hell

asyncOperation1(data1,function (result1) {
    asyncOperation2(data2,function(result2){
        asyncOperation3(data3,function (result3) {
            asyncOperation4(data4,function (result4) {
                //do something
            })
        })
    })
})

这种代码不仅可读性很差,而且在团队中很不好维护。 之后还衍生中一种事件监听事件,比如:

element.addEventListener('click',function(){
//response to user click    
});

也就是click事情的回调函数只在触发了click事件之后才执行,当然了,这也是回调函数的一种变种。

####Promise时代 promise,顾名思义,就是承诺,这个承诺有成功初始(pending)(fulfilled)和失败(rejected)三种状态。当由pending->fulfilled状态时,会触发resolved,当由pending->rejected状态时,会触发rejected.具体规范可以参见promise/A+规范。 promise有一个then函数,它返回一个promise对象,就是因为这样,promise才可以实现链式调用。promise的链式调用可以用如下图示表示: 输入图片说明

根据promise的概念,上面的回调函数嵌套过深的问题可以写成如下:

asyncOperation1(data)
    .then(function (data1) {
        return asyncOperation2(data1)
    }).then(function(data2){
        return asyncOperation3(data2)
    }).then(function(data3){
    return asyncOperation(data3)
})

####generator/yield时代 ES6语法中引入了generator,一个普通的generator函数表示如下:

function* gen(){
    yield 1;
    yield 2;
    return 'ending';
}
var g = gen();
g.next(); //{value:1,done:false}
g.next(); //{value:2,done:false}
g.next(); //{value:ending,done:true}

调用 Generator函数,会返回一个内部指针 。即执行它不会返回结果,返回的是指针对象。调用指针 gnext 方法,将会指向第一个遇到的yield 语句,yield的作用是暂停此处,只有调用next函数才会执行下一个yield。每次调用next 方法,会返回一个对象,表示当前阶段的信息( value 属性和done 属性)。value 属性是yield语句后面表达式的值,表示当前阶段的值;done属性是一个布尔值,表示 Generator函数是否执行完毕,即是否还有下一个阶段。上面的深度嵌套的例子改写为generator如下:

function* generateOperation(data1) {
    var result1 = yield asyncOperation1(data1);
    var result2 = yield asyncOperation2(result1);
    var result3 = yield asyncOperation3(result2);
    var result4 = yield asyncOperation4(result3);
    //more
}

####async/await ES7出现了async/await,从字面意思就可以看出来代码在执行过程中等待,上面的代码变成async./await形式如下:

async generateOperation(data1) {
    var result1 = await asyncOperation1(data1);
    var result2 = await asyncOperation2(result1);
    var result3 = await asyncOperation3(result2);
    var result4 = await asyncOperation4(result3);
    //more
}

generator和async虽然在形式和代码结构上很相似,但是两者还是有区别的:

  • async的语义化更好
  • async内置了自动执行器,之前我们说过generator需要手动调用next()方法来执行下一个yield语句,但是async会自动执行内部的异步函数,而generator需要结合co来实现自动执行所有的异步函数 -async 扩展性更好,generatorco结合时候,要求在yield语句后面是一个thunk函数或者promise,而await后面则可以是任何数据类型,比如StringNumber

© 著作权归作者所有

共有 人打赏支持
sunshinewyf
粉丝 15
博文 97
码字总数 64205
作品 0
武汉
程序员
前端路由的前生今世及实现原理

😶😶 原文发于我的博客:https://github.com/hwen/blogS... 什么是路由 路由这个概念最先是后端出现的。在以前用模板引擎开发页面时,经常会看到这样 有时还会有带或的路径,这就是所谓的...

hwencc
2017/11/12
0
0
前端通信:ajax设计方案(五)--- 集成promise规范,更优雅的书写代码

  距离上一篇博客书写,又过去了大概几个月了,这段时间暂时离开了这个行业,让大脑休息一下。一个人旅行,一个人休息,正好也去完成一个目标 --- 拥有自己的驾照。当然,也把自己晒的黑漆...

仲强
2017/06/30
0
0
三个分享——异步流程控制 / Modern Node.js/Java项目如何与Node.js共存

分享1《深入浅出js(Node.js)异步流程控制》 StuQ分享专题《深入浅出js(Node.js)异步流程控制》 InfoQ 前端之巅分享 精简版 摘要 目前在js流程控制领域越来越乱,各种派系。。。比如promi...

i5ting
2016/07/18
1K
6
前端工具之WebPack解密--背景

请注意,这是一篇站在完全新手的角度上来写的文章。可能你是一个后端人员想了解前端工具的使用和概念;也可能你是一个前端小菜(还在DIV+CSS的世界里挣扎着)。本文比较适合那些以前完全没有接...

JavaSwing
2016/11/29
428
0
前端协作流程

Web系统   在介绍协作流程之前,首先简单地了解Web系统的结构   从宏观上来说,Web系统是部署在服务器上用于为web客户端提供服务的系统。不同的Web客户端根据不同的需求,发送请求到服务...

sshpp
2017/07/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

70.shell的函数 数组 告警系统需求分析

20.16/20.17 shell中的函数 20.18 shell中的数组 20.19 告警系统需求分析 20.16/20.17 shell中的函数: ~1. 函数就是把一段代码整理到了一个小单元中,并给这个小单元起一个名字,当用到这段...

王鑫linux
34分钟前
0
0
分布式框架spring-session实现session一致性使用问题

前言:项目中使用到spring-session来缓存用户信息,保证服务之间session一致性,但是获取session信息为什么不能再服务层获取? 一、spring-session实现session一致性方式 用户每一次请求都会...

WALK_MAN
56分钟前
3
0
C++ yield()与sleep_for()

C++11 标准库提供了yield()和sleep_for()两个方法。 (1)std::this_thread::yield(): 线程调用该方法时,主动让出CPU,并且不参与CPU的本次调度,从而让其他线程有机会运行。在后续的调度周...

yepanl
今天
3
0
Java并发编程实战(chapter_3)(线程池ThreadPoolExecutor源码分析)

这个系列一直没再写,很多原因,中间经历了换工作,熟悉项目,熟悉新团队等等一系列的事情。并发课题对于Java来说是一个又重要又难的一大块,除非气定神闲、精力满满,否则我本身是不敢随便写...

心中的理想乡
今天
23
0
shell学习之获取用户的输入命令read

在运行脚本的时候,命令行参数是可以传入参数,还有就是在脚本运行过程中需要用户输入参数,比如你想要在脚本运行时问个问题,并等待运行脚本的人来回答。bash shell为此提 供了read命令。 ...

woshixin
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部