异步函数封装请确保异步性(Javascript需要养成的良好习惯)
背景假设:
你有许多的配置信息存放在服务器上,因为配置太多,不希望每次都把所有的配置信息都写到前端,希望能需要用的时候再获取就好了。
因为Javascript单线程运行,你不希望堵塞ui渲染于是你专门写了个异步获取函数(ajax获取后台信息)
var getConfig=function(key,callback){
$.get('/config/'+key,function(config){
callback(null,config);
},'json');
};
//使用该函数
getConfig(1,function(err,config){
if(err){
return console.log(err);
}
console.log(config);
});
于是就可以欢快的使用它了。
你发现你的Javascript里面调用它的地方很多,每次都发起一个请求太费时间和资源,于是你打算给它加上缓存(为了说明问题,我们不用高阶函数:) )。
var getConfig = (function () {
var _configs = {};//缓存容器
return function (key, callback) {
if (_configs[key] === undefined) {
$.get('/config/' + key, function (config) {
_configs[key] = config;
callback(null, config);
}, 'json');
} else {
return callback(null,_configs[key]);
}
};
})();
于是你就可以欢快的使用配置了,获取过的配置都会被缓存。
问题就出在这里,你运行以下代码
getConfig('db',function(err,config){
console.log(config);//输出2
});
console.log('hello world');//输出1
在我们添加缓存之前的版本,我们每次运行该代码 都是先输出1,再输出2。但是在我们加了缓存后,假如缓存存在的话,我们的输出就变成了先输出2,再输出1,这样的情况或许在我们的事例中好像没有什么影响,但在有些情景下将会留下一些比较奇怪的bug。
这里的问题就是一个异步的不一致性问题,解决该问题可以这样。
var getConfig = (function () {
var _configs = {};//缓存容器
return function (key, callback) {
if (_configs[key] === undefined) {
$.get('/config/' + key, function (config) {
_configs[key] = config;
return callback(null, config);
}, 'json');
} else {
setTimeout(function(){//改动的地方
return callback(null,_configs[key]);
},0);
}
};
})();
我们需要把callback的运行放到下一个tick中才运行,已保持getConfig函数的异步性质。
结论:当封装函数的时候如果是一个异步函数的时候,需要确保函数的回调一直都是异步的。(这里是个新手(如我)常见的小问题,但是养成一种好的习惯,有助于保证代码的健壮性)
PS:如果你需要确保一个函数是一个异步函数,可以考虑下 async 的 async.ensureAsync方法(巧妙的运用同异步的差异实现) https://github.com/caolan/async
如果你考虑对你的方法做结果缓存,同样可以考虑 async 的 async.memoize方法(更完整,不单单缓存结果,还为高并发情况做了处理多个相同请求并发只会触发一次计算)。
ensureAsync
异步函数封装请确保异步性(Javascript需要养成的良好习惯)的更多相关文章
- callback res.end 记得return(Javascript需要养成的良好习惯)
错误示例: app.get('do',function(req,res,next){ getUserId(function(err,userId){ if(err){ res.end(err);//错 ...
- 『审慎』.Net4.6 Task 异步函数 比 同步函数 慢5倍 踩坑经历
异步Task简单介绍 本标题有点 哗众取宠,各位都别介意(不排除个人技术能力问题) —— 接下来:我将会用一个小Demo 把 本文思想阐述清楚. .Net 4.0 就有了 Task 函数 —— 异步编 ...
- Net4.6 Task 异步函数 比 同步函数 慢5倍 踩坑经历
Net4.6 Task 异步函数 比 同步函数 慢5倍 踩坑经历 https://www.cnblogs.com/shuxiaolong/p/DotNet_Task_BUG.html 异步Task简单 ...
- 简述异步编程&Promise&异步函数
前言:文章由本人在学习之余总结巩固思路,不足之前还请指出. 一.异步编程 首先我们先简单来回顾一下同步API和异步API的概念 1.同步API:只有当前的API执行完成之前,才会执行下一个API 例: ...
- 更优雅的方式: JavaScript 中顺序执行异步函数
火于异步 1995年,当时最流行的浏览器--网景中开始运行 JavaScript (最初称为 LiveScript). 1996年,微软发布了 JScript 兼容 JavaScript.随着网景.微 ...
- Node.js用ES6原生Promise对异步函数进行封装
Promise的概念 Promise 对象用于异步(asynchronous)计算..一个Promise对象代表着一个还未完成,但预期将来会完成的操作. Promise的几种状态: pending:初 ...
- JavaScript处理异步请求的几种方式(取异步函数返回值)
JavaScript处理异步的几种方式 Javascript语言的执行环境是"单线程"(single thread,就是指一次只能完成一件任务.如果有多个任务,就必须排队,前面一个 ...
- 获取JavaScript异步函数的返回值
今天研究一个小问题: 怎么拿到JavaScript异步函数的返回值? 1.错误尝试 当年未入行时,我的最初尝试: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <s ...
- javascript 异步请求封装成同步请求
此方法是异步请求封装成同步请求,加上token验证,环境试用微信小程序,可以修改文件中的ajax,进行封装自己的,比如用axios等 成功码采用标准的 200 到 300 和304 ,需要可以自行修改 ...
随机推荐
- Mac系统下配置Maven环境变量
1.在官网下载Maven安装包,网址:https://maven.apache.org/download.cgi: 2.进入终端Terminal,验证JDK是否配置成功,输入java -version ...
- Less2css error 终极解决方案(转载)
用到less时遇到的问题 ,然后复制过来的 使用sublime Text3 的时候,安装less2Css后,和很多人一样以为大功告成,开始要运行编译less文件,结果开始发现 于是乎开始搜索问题和解决 ...
- json.stringfy()和json.parse()
json.stringfy()将对象.数组转换成字符串:json.parse()将字符串转成json对象. json.stringfy(): 语法: JSON.stringify(value [, ...
- JavaScript中关于地址的获取
//取当前页面名称(不带后缀名) function pageName(){ var a = location.href; var b = a.split("/"); var c = ...
- Android文件存储
文件存储是Android中最基本的一种数据存储方式,它不读存储的内容进行任何的格式化处理,所有数据原封不动的保存在文件之中.如果想用文件存储的方式保存一些较为复杂的数据,就需要定义一套自己的格式规范, ...
- iOS 页面间几种传值方式(属性,代理,block,单例,通知)
第二个视图控制器如何获取第一个视图控制器的部分信息 例如 :第二个界面中的lable显示第一个界面textField中的文本 这就需要用到属性传值.block传值 那么第一个视图控制器如何获的第二个视 ...
- Android 防止OOM优化
1. Android2.x及以下的系统优化: Bitmap被解码后的像素被存储在Native Heap中, Dalvik Heap有个external计数,记录了Bitmap所占用的内存. 当 Dal ...
- 微信webview
会露出灰色的地步 https://segmentfault.com/q/1010000004295291 有说用iscroll5来解决,但是明显有bug啊 https://segmentfault.c ...
- linux上使用shell脚本查看内存使用率
如上的内存利用率 = [-/+buffers/cache:used]/[Mem:total ] = 6293404 / 16333656 对于free命令而言,有如下公式: total = used ...
- JavaScript实现快速排序
思想: 通过分治思想.递归方法将数据依次分解为包含较小元素和较大元素的不同子序列 1.在数组中选择一个元素为基准 2.对数组进行遍历,小于基准的元素都移到基准的左边,大于基准的元素都移到基准的右边 3 ...