异步函数封装请确保异步性(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 ,需要可以自行修改 ...
随机推荐
- python操作Excel--使用xlrd
一.安装xlrd http://pypi.python.org/pypi/xlrd 二.使用介绍 1.导入模块 import xlrd 2.打开Excel文件读取数据 data = xlrd.open ...
- Spark学习(三) -- SparkContext初始化
标签(空格分隔): Spark 本篇博客以WordCount为例说明Spark Job的提交和运行,包括Spark Application初始化.DAG依赖性分析.任务的调度和派发.中间计算结果的存储 ...
- centos 6.4 升级python到版本2.7.12
注意:需要root权限 查看python版本:python --version 1.下载Python-2.7.12wget https://www.python.org/ftp/python/2.7. ...
- shell编程之变量
变量: 变量由字母.数字._ 组成,不能以数字开头 长度不能超过255个字符 在bash中,变量的默认类型是字符串类型 变量分类: 1.用户自定义变量:只在当前shell生效,是局部变量 定义方法: ...
- OpenCV从入门到放弃系列之——如何扫描图像、利用查找表和计时
目的 如何遍历图像中的每一个像素? OpenCV的矩阵值是如何存储的? 如何测试我们所实现算法的性能? 查找表是什么?为什么要用它? 测试用例 颜色空间缩减.具体做法就是:将现有颜色空间值除以某个输入 ...
- SQL查出异常数据(ORA-01722: 无效数字)
-- Created on 2015/4/29 by MENGHU DECLARE -- Local variables here I INTEGER; BEGIN FOR OPEN_DATA IN ...
- EasyUI 的Tab 标签添加右键菜单
样式: 主要提供右键功能代码. (只需要提供你需要的js和css就行了) <!doctype html> <html> <head> <base href=& ...
- MySQL DDL 整理
DDL is Data Definition Language statements. Some examples:数据定义语言,用于定义和管理 SQL 数据库中的所有对象的语言 -- 清空表内容 T ...
- text-transform属性
text-transform -- 定义文本的大小写状态,此属性对中文无意义 取值:capitalize | uppercase | lowercase | none | inherit capita ...
- windows下安装beautifulsoup4
方法一: pip install beautifulsoup4 方法二: 在官网下载安装包后,放在python目录下--运行cmd--进入bs4安装包路径--输入setup.py install 测试 ...