7 lines JavaScript library for calling asynchronous functions
I was surprised by the good feedback for JavaScript template engine in just 20 lines and decided to blog for another small utility function which I'm using often. While we are talking about JavaScript in the browser, most of the operations are asynchronous. We are dealing with callbacks all the time and sometimes we end up with awesome callback hell.
Let's say that we have two functions and we want to call them one after each other. They both operate with same variable. The first one sets its value and the second one uses it.
var value; var A =function(){ setTimeout(function(){ value =10; },200); }; var B =function(){ console.log(value); }; 调用方法: A(); B(); 执行结果: undefined
So, if we now run A();B(); we will get undefined in the console. It's like that because the A function sets the value asynchronously. What we could do is to send a callback and execute it once the job is done.
var value; var A =function(callback){ setTimeout(function(){ value =10; callback(); },200); }; var B =function(){ console.log(value); }; A(function(){ B(); }); 执行结果: 10
This works, but imagine what will happen if we need to run five or more methods. Passing callbacks all the time will lead to messy and unpleasant code.
The idea is to write a helper function which accept our workers and handle the whole process. Let's start with the simplest thing:
var queue =function(funcs){ // magic here }
So, what we have to do is to run that function by passing the both A and B - queue([A, B]). We need to get the first function and execute it.
var queue =function(funcs){ var f = funcs.shift(); f(); }
If you run this code you will see an error TypeError: undefined is not a function. That's because A function doesn't accept callback but it tries to run it. Let's pass one.
var queue =function(funcs){ varnext=function(){ // ... }; var f = funcs.shift(); f(next); };
The next method is getting called once A finishes its job. That's the perfect place for continuing to the next function in the list. We could arrange the code a bit and we are able to go through the whole array.
var queue =function(funcs){ varnext=function(){ var f = funcs.shift(); f(next); }; next(); };
If we leave the things like that we will reach our goal. I.e. function A is called and just after that B, which prints the correct value of the variable. The key moment here is the usage of shift method. It removes the first element of the array and returns the element. Step by step funcs array becomes empty. So, this could lead to an error. To prove this theory, let's assume that we still need to run the both functions, but we don't know their order. In this case, they both should accept callback and execute it.
var A =function(callback){ setTimeout(function(){ value =10; callback(); },200); }; var B =function(callback){ console.log(value); callback(); };
And of course we got TypeError: undefined is not a function. To prevent this we should check if the funcs array is empty.
var queue =function(funcs){ (functionnext(){ if(funcs.length >0){ var f = funcs.shift(); f(next); } })(); };
What I did also is to invoke the next function just after its definition. It saves few bytes.
Let's try to cover as many cases as possible. What about the current scope of the executed functions. The this keyword inside the functions probably points the global window object. It will be cool if we set our own scope.
var queue =function(funcs, scope){ (functionnext(){ if(funcs.length >0){ var f = funcs.shift(); f.apply(scope,[next]); } })(); };
We added one more parameter to the tiny library. Later instead of f(next) we use the apply function, set the scope and pass next as a parameter. Pretty much the same thing.
And the last feature which we need is the ability pass arguments between the functions. Of course we don't have an idea how many parameters will be send. That's why we need to use the arguments variable. As you probably know, that variable is available in every JavaScript function and represents the coming parameters. It's something like an array, but not exactly. And because in apply method we need to use real array, a little trick is used.
var queue =function(funcs, scope){ (functionnext(){ if(funcs.length >0){ var f = funcs.shift(); f.apply(scope,[next].concat(Array.prototype.slice.call(arguments,0))); } })(); };
And here is the full example which demonstrates all the features of the library.
var obj ={ value:null }; queue([ function(callback){ varself=this; setTimeout(function(){ self.value =10; callback(20); },200); }, function(callback, add){ console.log(this.value + add); callback(); }, function(){ console.log(obj.value); } ], obj);
If you run this code you will see:
30 10
And to match the lines mentioned in the title of this article we could write the main code in only one line:
var queue =function(funcs, scope){ (functionnext(){ if(funcs.length >0){ funcs.shift().apply(scope ||{},[next].concat(Array.prototype.slice.call(arguments,0))); } })(); };
Here is a JSBin to play with:
var queue = function(funcs, scope) { (function next() { if(funcs.length > 0) { funcs.shift().apply(scope || {}, [next].concat(Array.prototype.slice.call(arguments, 0))); } })(); }; var obj = { value: null }; queue([ function(callback) { var self = this; setTimeout(function() { self.value = 10; callback(20); }, 200); }, function(callback, add) { console.log(this.value + add); callback(); }, function() { console.log(obj.value); } ], obj); queue();
原文网址:http://krasimirtsonev.com/blog/article/7-lines-JavaScript-library-for-calling-asynchronous-functions
译文网址:http://blog.jobbole.com/60046/
相关推荐
C#JS AJAX部分代码 用于前后台的数据同步
JQuery,JQuery,JQuery,JQuery,JQuery,JQuery,JQuery,JQuery,JQuery,JQuery,JQuery,JQuery,ajax,ajax,ajax,ajax,ajax,ajax,ajax,ajax,ajax,ajax,ajax,ajax,ajax,ajax,ajax,ajax,一个关于在js中通过JQuery实现异步无...
Theseus - 一种新型的JavaScript调试器具有实时代码覆盖率、追溯检查和异步调用树
V8 最早被开发用以嵌入到 Google 的开源浏览器 Chrome 中,但是 V8 是一个可以独立的模块,完全可以嵌入您自己的应用,著名的 Node.js( 一个异步的服务器框架,可以在服务端使用 JavaScript 写出高效的网络服务器 ) ...
OC调用JS方法, JS代码向OC发出指令. 这是一个初级的JS和OC相互沟通, 如果项目需求比较完美,可以进行改进, 比如说 异步调用,JS带参函数传递返回值等等的交互模式,还需要具体功能改进. 对于没弄过交互的同学 看着代码...
JavaScript异步调用定时方法并停止该方法实现代码 ,需要的朋友可以参考下
调用方法:1 将下载好的Ajax js文件引用到页面 代码如下:<script src " js MyAjax js" type "text javascript">< script> 2 调用方法:(1)异步: MyAjax " 要调用的方法...
Node.js通过pg模块连接OpenGauss数据库,已封装为同步模块,可在异步代码中直接调用。
我们经常在Silverlight中与服务器交互,例如Silverlight和SharePoint交换信息,常用的方式是通过Javascript利用xmlhttp向服务器端发送请求或调用Webservice。这里就涉及到同步和异步的问题,如果采用同步调用,则会...
在实际编码中,我们经常会遇到Javascript代码异步执行的场景,比如ajax的调用、定时器的使用等,在这样的场景下也经常会出现这样那样匪夷所思的bug或者糟糕的代码片段,那么处理好你的Javascript异步代码成为了异步...
代码如下: Async = { Operation: { var callbackQueue = []; this.result = undefined; this.state = “waiting”; this.completed = false; } } addCallback方法 接下来,我们要实现addCallba
async/await多个函数关联调用 async/await使得异步代码看起来像同步代码 ...所以在模拟异步调用函数时,函数体内返回promise async/await缺点 async函数里,无论是Promise reject的数据还是逻辑报错,
然而在单线程的JavaScript编程中,XHR异步调用的代码风格实在是与一般的JavaScript代码格格不入。 额外参数 考虑一个除法函数,如果它是纯客户端的同步函数,那么签名会是这样的: function divide(operand1, ...
LightningJS安全、快速、异步嵌入代码用于第三方Javascript交付
在PHONEGAP新手开发插件的时候,总会遇到一些NATIVE调用JS的代码问题,这里给出了一个OBJECTIVE-C 与 JS通过UIWEBVIEW进行相互调用的例子,给定了同步调用与异步调用的方法更多详细的部分请参考KAITIREN博客;
Android与JS之间跨平台异步调用 为什么突然要搞这个问题呢? 在开发浏览器的时候遇到这个狗血的问题,花了将近1天的时间才想到这个解决方案,Android与JavaScirpt互调。 因为接口是抓取的别人的,所以出现了...
因为javascript默认情况下是单线程的,这意味着代码不能创建新的线程来并行执行。但是对于最开始在浏览器中运行的javascript来说,单线程的同步执行环境显然无法满足页面点击,鼠标移动这些响应用户的功能。于是...
附件包含最新的ajaxPro.dll9.2.17.1版本及其WebConfig配置文件,使用时只需要将ajaxPro.2.dll添加至工程引用,并覆盖原有配置文件即可...具体使用方法测试代码中详细列出,包含了传参调用和不传参数调用,均已测试通过
它是一个实用程序,允许您在任何 DOM 事件上异步调用服务器方法,就像调用 javascript 方法一样,而无需为 ajax 支持编写一段代码。 它依赖于 jquery,适用于所有版本的 jquery。 文档和工作在这里 -
在上一篇文章里面,我们为异步调用框架设计了一种链式调用方式,来增强异步调用队列的代码可读性,现在我们就来编写实现这部分功能的代码。