异步函数封装请确保异步性(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函数的异步性质。

结论:当封装函数的时候如果是一个异步函数的时候,需要确保函数的回调一直都是异步的。(这里是个新手(如我)常见的小问题,但是养成一种好的习惯,有助于保证代码的健壮性)

时间: 2024-10-21 16:54:36

异步函数封装请确保异步性(Javascript需要养成的良好习惯)的相关文章

callback res.end 记得return(Javascript需要养成的良好习惯)

错误示例: app.get('do',function(req,res,next){ getUserId(function(err,userId){ if(err){ res.end(err);//错误位置 } getHeadPicByUserId(userId,function(){ }); }); }); var getHeadPicByUserId=function(userId,callback){ if(typeof userId!=='number'){ callback('用户名非

同步函数与异步函数

依据微软的MSDN上的解说: (1)   同步函数:当一个函数是同步执行时,那么当该函数被调用时不会立即返回,直到该函数所要做的事情全都做完了才返回. (2)   异步函数:如果一个异步函数被调用时,该函数会立即返回尽管该函数规定的操作任务还没有完成. (3) 在一个线程中分别调用上述两种函数会对调用线程有何影响呢? 当一个线程调用一个同步函数时(例如:该函数用于完成写文件任务),如果该函数没有立即完成规定的操作,则该操作会导致该调用线程的挂起(将CPU的使用权交给系统,让系统分配给其他线程使用

QT 异步函数和同步函数交换问题

同步函数与异步函数 依据微软的MSDN上的解说: (1)   同步函数:当一个函数是同步执行时,那么当该函数被调用时不会立即返回,直到该函数所要做的事情全都做完了才返回. (2)   异步函数:如果一个异步函数被调用时,该函数会立即返回尽管该函数规定的操作任务还没有完成. (3) 在一个线程中分别调用上述两种函数会对调用线程有何影响呢? 当一个线程调用一个同步函数时(例如:该函数用于完成写文件任务),如果该函数没有立即完成规定的操作,则该操作会导致该调用线程的挂起(将CPU的使用权交给系统,让系

Node.js用ES6原生Promise对异步函数进行封装

版权声明:本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可.转载请注明来源http://blog.csdn.net/azureternite 目录(?)[+] Promise的概念 Promise 对象用于异步(asynchronous)计算..一个Promise对象代表着一个还未完成,但预期将来会完成的操作. Promise的几种状态: pending:初始状态,即等待操作的执行 fulfilled:成功的操作 rejected:失败的操作 pending的状态

获取JavaScript异步函数的返回值

今天研究一个小问题: 怎么拿到JavaScript异步函数的返回值? 1.错误尝试 当年未入行时,我的最初尝试: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <script> function getSomething() {  var r = 0;  setTimeout(function() {  r = 2;  }, 10);  return r; } function compute() {  var x = getSomething();  alert

javascript 异步请求封装成同步请求

此方法是异步请求封装成同步请求,加上token验证,环境试用微信小程序,可以修改文件中的ajax,进行封装自己的,比如用axios等 成功码采用标准的 200 到 300 和304 ,需要可以自行修改 同步任务接入之后,每个任务会进行token的验证,每个任务之间都是同步请求,包括token /** * 同步流请求 * token验证每个接口 * 柯里化添加同步任务 * resolve返回res,cb * reject 返回res,cb * 通过任务中断测试 * 通过成功失败回调函数测试 * *

JavaScript异步编程(一) 深入理解JavaScript事件

JavaScript异步编程 深入理解JavaScript事件 ?事件的调度 JavaScript事件处理器在线程空闲之前不会运行 线程的阻塞 var start = new Date(); // setTimeout和setInterval的计时精度比期望值差 setTimeout(function(){ var end = new Date(); console.log('Time elapsed', end - start, 'ms'); }, 500); while(new Date -

ES2017异步函数现已正式可用

ES2017标准已于2017年6月份正式定稿了,并广泛支持最新的特性:异步函数.如果你曾经被异步 JavaScript 的逻辑困扰,这么新函数正是为你设计的. 异步函数或多或少会让你编写一些顺序的 JavaScript 代码,但是却不需要在 callbacks.generators 或 promise 中包含你的逻辑. 如下代码: function logger() {     let data = fetch('http://sampleapi.com/posts')     console.

【前端】Util.js-ES6实现的常用100多个javaScript简短函数封装合集(持续更新中)

Util.js (持续更新中...) 项目地址: https://github.com/dragonir/Util.js 项目描述 Util.js 是对常用函数的封装,方便在实际项目中使用,主要内容包含:数组类.浏览器类.日期类.函数类.数学类.媒体类.节点类.对象类.字符串类.类型检测类.正则表达式类等内容. 使用方法 1. 引入Bable transpiler以保证支持ES6 <script type="javascript/text" src="./browser