ES6__异步开发优化
一:JS事件循环
1:同步调用
同步调用是一种阻塞式调用,调用要等待双方执行完毕才返回,他是一种单向调用。
2:回调
回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口。
3:异步调用
异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方,比如浏览器点击事件中,用户点击后,会调用JS中的回调函数。
异步的实现原理:
首先左上角的Call stack(调用栈)会把代码一行一行的执行,遇到addEVentListener,也就是事件,那么它不会执行,会托管在implementation-specific(可以理解为浏览器)中,右上角的implementation-specific会把这个事件记下来,当有人点击时,那么它会load成一个消息存放在右下角的message queue中,然后Event Loop(事件循环)会一直在那里循环,查看message queue中的消息,有消息,就把它扔回调用栈,然后执行call back的事件。
二:ES6
阮大大的《ECMAScript入门》 http://es6.ruanyifeng.com/
1: promise
new Promise((resolve, reject) => {
console.log('begin promise')
setTimeout(resolve, 1000)
}).then(() => {
console.log('over')
})
这个是非常简单的代码,先new promise传入2个参数,resolve代表成功会怎么样,reject代表失败会怎么样,上面的代码的意思是先输出'begin promise'resolve成功后1秒后输出'over'。then()的意思是resolve之后立即执行。
new Promise((resolve,reject)=>{
console.log('begin')
setTimeout(function() {
resolve();
},1000);
}).then(()=>{
console.log('1')
return new Promise((resolve,reject)=>{
setTimeout(function() {
resolve();
},1000);
});
}).then(()=>{
console.log('2');
return new Promise((resolve)=>{
setTimeout(function(){
resolve();
}, 1000)
})
}).then(()=>{
console.log('over');
})
代码依次执行后会出现'begin',1,2,'over'。
return new Promise的意思就是返回一个new promise, 放在上一个promise对象上,形成链式调用,新的promise就代表this的上下文,与上面的promise形成相同的结果。
,我们发现整一个过程就像一个瀑布流一样,但是它都嵌套在一起了。非常的不友好。
2:thunk/curry化函数
thunkAsync = thunkify(async)
thunkAsync(params)(callback)
var Thunkify = function(fn){
return function(){
var args = Array.prototype.slice.call(arguments);
return function(callback){
//2000,callback
args.push(callback);
return fn.apply(this,args)
}
}
} var thunkTimeout = Thunkify((time,callback)=>{
setTimeout(callback, time)
}) //thunkTimeout(time)(callback)
thunkTimeout(2000)(()=>{
console.log('success');
})
thunkify的意思:先传入一个元素setTimeout(),但是它没有被立即调用,是先放在了这里,然后有返回了一个函数,返回的这个函数是把arguments里面的东西存起来,有就是2000,然后又返回一个函数,这个返回函数传入的才是最终的callback,在这个函数中有把callback push给了args,那么args的状态就是2000,callback,然后最后一个return就是进行一开始我们保存的setTimeout的调用。
3:generator
function* helloGenerator(){
console.log('generator');
yield 'world'
console.log('finish')
}
// //执行generator
var generatorResult = helloGenerator();
console.log(generatorResult.next().value);
console.log(generatorResult.next());
generator要记住2点,next和yield,我们可以通过next()来控制yield的执行。next是继续执行,yield是暂停。
var gen = function* (){
//把刚才的thunk函数拿过来,放在yield的后面
//只需要接着传一个callback就可以执行了
var r1 = yield thunkTimeout(2000);
console.log(r1);
//把刚才的thunk函数拿过来,放在jield的后面
//只需要接着传一个callback就可以执行了
var r2 = yield thunkTimeout(2000);
console.log(r2)
}
//这是一个手动执行的版本
var g = gen();
//这个value指向的是,刚才我们已经传入的setTimeout(2000)
g.next().value(function(){
//这个function就是我们的callback
//在i这里,已经完成了第一个setTimeout的过程
var r2 = g.next('the first function complete');
//这里的value,指向的是第二个setTimeout(2000)
r2.value(function(){
//完全的执行
g.next('the second function complete');
})
})
三:异步优化
//像这样才能向上面那样2秒2秒的执行
setTimeout(function(){
console.log('the first function complete')
setTimeout(function(){
console.log('the second function complete')
}, 2000)
}, 2000)
我们要想实现上面的效果,有不想一直的嵌套。怎么办?
//thunk/curry化函数
var Thunkify = function(fn){
//传入一个functuion:setTimeout
//这个function fn,没有被立即调用,而是被放在了这里,先不管
//返回了另一个函数
return function(){
//把arguments里面的东西存了起来,2000
var args = Array.prototype.slice.call(arguments);
//又返回了一个新的函数
//这个函数传入的,才是最终的callback
return function(callback){
//完成push以后,args的状态是什么
//2000,callback
args.push(callback);
//最终在进行一开始我们保存的setTimeout的调用
return fn.apply(this,args)
}
}
} var thunkTimeout = Thunkify((time,callback)=>{
setTimeout(callback, time)
}) var gen = function* (){
//把刚才的thunk函数拿过来,放在jield的后面
//只需要接着传一个callback就可以执行了
var r1 = yield thunkTimeout(1000);
console.log('the first function1 complete');
var r2 = yield thunkTimeout(2000);
console.log('the first function2 complete');
var r3 = yield thunkTimeout(3000);
console.log('the first function3 complete');
var r4 = yield thunkTimeout(4000);
console.log('the first function4 complete');
var r5 = yield thunkTimeout(5000);
console.log('the first function5 complete');
} function run(gen){
//第一次把generator执行
var g = gen();
function nextRun(r){
//在第一个行进行了一次next
var next = g.next(r);
if(next.done == true){
return;
}
if(typeof next.value.then == 'function'){ //promise要加一个then,才执行,所以这里加一个判断
next.value.then(nextRun)
}else{
//第一次value
next.value(nextRun)
}
}
nextRun();
}
run(gen);
run函数就是用了递归,递归简单点来说,就是自己调用自己。
OK,大功告成。我好像还是第一次写这么认真的博客。
ES6__异步开发优化的更多相关文章
- 微信小程序开发优化
一.开发优化一 1.使用Vant Weapp 1.1 什么是Vant Weapp Vant Weapp官网链接 Vant Weapp是有赞前端团队开源的一套小程序UI组件库,助力开发者快速搭建小程序应 ...
- [Android] Android开发优化之——使用软引用和弱引用
Java从JDK1.2版本开始,就把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期.这四种级别由高到低依次为:强引用.软引用.弱引用和虚引用. 这里重点介绍一下软引用和弱引用. ...
- Android开发优化之——对Bitmap的内存优化
http://blog.csdn.net/arui319/article/details/7953690 在Android应用里,最耗费内存的就是图片资源.而且在Android系统中,读取位图Bitm ...
- Android开发优化之——使用软引用和弱引用
Java从JDK1.2版本开始,就把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期.这四种级别由高到低依次为:强引用.软引用.弱引用和虚引用. 这里重点介绍一下软引用和弱引用. 如果 ...
- JavaScript 异步开发全攻略(转)
写了一本介绍 JavaScript 异步开发的小书: https://meathill.gitbooks.io/javascript-async-tutorial/content/ 除了比较详细的介绍 ...
- [原]Android开发优化-Adapter优化
ListView作为Android开发中使用频率最高的一个控件,保证ListView的流畅运行,对用户体验的提高至关重要.Adapter是ListView和数据源之间的中间人,当每条数据进入可见区时, ...
- NET中并行开发优化
NET中并行开发优化 让我们考虑一个简单的编程挑战:对大数组中的所有元素求和.现在可以通过使用并行性来轻松优化这一点,特别是对于具有数千或数百万个元素的巨大阵列,还有理由认为,并行处理时间应该与常规时 ...
- [Android] Android开发优化之——对界面UI的优化(2)
在Android应用开发过程中,屏幕上控件的布局代码和程序的逻辑代码通常是分开的.界面的布局代码是放在一个独立的xml文件中的,这个文件里面是树型组织的,控制着页面的布局.通常,在这个页面中会用到很多 ...
- [Android] Android开发优化之——对界面UI的优化(1)
在Android应用开发过程中,屏幕上控件的布局代码和程序的逻辑代码通常是分开的.界面的布局代码是放在一个独立的xml文件中的,这个文件里面是树型组织的,控制着页面的布局.通常,在这个页面中会用到很多 ...
随机推荐
- SD卡兼容性问题(转)
看到一篇关于硬件抗干扰的应用实例,很有参考值.所以,转过来方便查找. 源文:SD卡兼容性问题 最近碰到了一个SD卡兼容性的问题.主芯片SD卡组的信号,经过转接板,长排线,然后再到SD卡子板之后.对多种 ...
- ios-Ineligible Devices 不被识别的设备
此问题大致分为几种: 1.设备不可用,出现Ineligible Devices,如下图: 此错误因为 Xcode的Deployment Target 大于设备的,选择和设备一样 或者 低于设备的.如下 ...
- IOS开发-OC学习-Info.plist文件解析
Info.plist文件是新建ios项目完成后自动生成的一个配置文件,在Xcode中如下图: 通过解析可以获得配置的具体细节,解析过程如下: // 定义一个nsstring用来获取Info.plist ...
- Unity3D ——强大的跨平台3D游戏开发工具(五)
第九章 图形用户界面类G.U.I 您在玩很多3D游戏的时候,不知是否注意到在游戏界面中,总有一些图形和文字信息是不随着3D视角的改变而改变的.这也是由于游戏本身的要求而决定的.比如说英雄的生命值,聊天 ...
- 测试部署环境用到的主要linux命令
1 部署前检查开发是否上传部署文档 2 在测试组中告知大家 3 将上一版本进行备份(cp -r neiguan-tomcat/ /home/personal/backup/neiguan-tomcat ...
- PHP 魔术变量和魔术函数详解
魔术变量 PHP 向它运行的任何脚本提供了大量的预定义常量. 不过很多常量都是由不同的扩展库定义的,只有在加载了这些扩展库时才会出现,或者动态加载后,或者在编译时已经包括进去了. 有八个魔术常量它们的 ...
- 10.TCP连接的建立与终止
1.建立连接协议 (1)请求端发送一个SYN段指明客户打算连接的服务器的端口,移机初始序号ISN.这个SYN段为报文段1. (2)服务器发回包含服务器的初始序号的SYN报文段作为应答.同时,将确认 ...
- WGCNA算法研究笔记
转自:http://www.gogoqq.com/ASPX/8390905/JournalContent/1303140588.aspx 研究了近半年的算法,记录下来给自己一个交代,也应该是考G前地最 ...
- 属性(Attribute)资源
前面已经介绍过自定义View组件的开发,自定义View组件与Android系统提供的View组件一样,即可在Java代码中使用,也可在XML界面布局代码中使用. 当在XML布局文件中使用Android ...
- WPF ResourceDictionary的使用
作用:一个应用程序中,某个窗口需要使用样式,但是样式非常多,写在一个窗口中代码分类不方便.最好Style写在专门的xaml文件中,然后引用到窗口中,就像HTML引用外部css文件一样. 初衷:就在于可 ...