`

[转]只有7行代码的异步调用 js 库

阅读更多

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/

分享到:
评论

相关推荐

    AJAX异步调用代码

    本文将深入解析标题为“AJAX异步调用代码”的内容,该段代码展示了如何使用C#与JavaScript结合,通过AJAX进行前后台数据的异步交互。 ### 一、理解AJAX及其工作原理 AJAX的核心在于`XMLHttpRequest`对象,它允许在...

    ice同步调用和异步调用实例代码

    Ice 是一种针对客户端和服务器进行通信的面向对象的中间件平台。Ice 为构建面向对象的客户-服务器应用提供了工具、API 和库支持。...客户和服务器可以分别部署,可以运行在...本代码为ice同步调用和异步调用实例代码。

    异步调用流程图

    在实际项目中,可以利用各种编程语言(如JavaScript的Promise、async/await,Java的CompletableFuture,或者.NET的async/await)来实现异步调用。 异步调用对于优化性能和提升用户体验至关重要。例如,在网页加载中...

    异步调用

    下面,我们以.NET的C#语言为例,看看如何在实际代码中使用异步调用: ```csharp using System; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { Console.WriteLine(...

    .net异步调用后台函数

    7. **异步调用的挑战与最佳实践**: 异步调用虽然能提升性能,但也需要注意一些问题,如资源管理、异常处理、同步原语(如锁)的使用等。应确保所有异步方法都正确地完成了,避免“悬挂”异步操作,并适当地处理...

    Struts2之异步调用机制详解案例struts014

    对于异步调用,我们可能需要配置一个能返回JSON或XML数据的结果类型,这些数据可以被JavaScript解析并用于更新页面。 6. **客户端逻辑**:在浏览器端,JavaScript代码需要监听用户触发的事件(如按钮点击),然后...

    asp.net异步调用后台方法提交

    本文将详细介绍如何在ASP.NET中实现异步调用后台方法,并解释相关的代码实现细节。 #### 一、异步调用背景与优势 异步调用是指在不阻塞主线程的情况下,向服务器发送请求并获取响应的过程。传统的同步调用方式会...

    ASP.NET异步调用

    在深入探讨“ASP.NET异步调用”这一主题前,我们先来理解其核心概念以及在实际场景中的应用。标题“ASP.NET异步调用”指的是在ASP.NET框架下,利用Ajax技术实现前后端的异步通信过程。具体而言,这里的异步调用主要...

    android JS与java代码相互调用

    在Android开发中,JavaScript(JS)与Java代码的相互调用是常见的需求,尤其是在混合式应用开发中。这种交互能够充分利用JavaScript的灵活性和Java的强大功能,实现更丰富的用户体验。本Demo旨在提供一个清晰、易懂...

    c++调用javascript代码

    CEF也支持异步调用,使得C++与JavaScript之间的通信更加流畅。 2. **Node.js的N-API**:虽然Node.js本身是用JavaScript编写的,但其提供了N-API,这是一个稳定的C/C++接口,用于创建可被JavaScript调用的原生模块。...

    使用ASP.NET AJAX异步调用Web Service和页面中的类方法

    ASP.NET AJAX 提供了一种强大的机制,使得开发者可以方便地在客户端JavaScript中异步调用Web Service和页面中的类方法,极大地简化了原本复杂的Ajax通信。这一特性是ASP.NET AJAX框架的核心优势之一,它允许开发者...

    ajax.net异步调用

    **Ajax.NET 异步调用详解** Ajax.NET 是 .NET Framework 中实现 AJAX(Asynchronous JavaScript and XML)技术的一种方式,它允许开发人员在不刷新整个网页的情况下更新页面的部分内容,从而提供更流畅、更快捷的...

    Node.js-Theseus-一种新型的JavaScript调试器具有实时代码覆盖率追溯检查和异步调用树

    本文将深入探讨“Node.js-Theseus”这一新型JavaScript调试器,它以其独特的实时代码覆盖率、追溯检查和异步调用树功能,为Node.js开发带来了全新的调试体验。 首先,我们来理解一下“Theseus”的核心特性——实时...

    Android与JS之间跨平台异步调用实例详解

    在异步调用中,通常会使用 RXJava 或其他异步处理库来处理网络请求。如代码所示,使用了 RXJava 的 `subscribeOn(Schedulers.io())` 来在后台线程执行网络请求,`observeOn(AndroidSchedulers.mainThread())` 则确保...

    JQuery中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实现异步无...

    Nodejs让异步变成同步的方法

    Node.js中让异步操作变成同步的方法通常是指将非阻塞的异步调用改写为在逻辑上表现得像同步调用的方式。Node.js中异步操作是通过回调函数、Promises和async/await等技术来实现的。以下我们详细讲解如何通过这些方法...

    ios-一行代码搞定JS调用OC.zip

    "ios-一行代码搞定JS调用OC.zip"提供的项目,通过`CHWebView`库,实现了简洁高效的JS与OC交互的方式。下面将详细介绍这个库及其工作原理。 `CHWebView`是开发者Chausson在GitHub上开源的一个轻量级库,其主要功能是...

    Ajax异步调用框架

    这个Ajax异步调用框架适用于简单的数据获取和页面局部更新,但现代Web开发中,更常见的是使用jQuery、axios、fetch等库来简化Ajax操作,它们提供了更友好的API和更好的兼容性。例如,jQuery的`$.ajax()`方法或者...

    异步调用_Async.rar

    异步调用是计算机编程中的一个关键概念,特别是在高性能、高并发和实时性要求较高的应用程序中。异步调用允许程序在等待某个操作完成时,继续执行其他任务,而不是阻塞等待,从而提高了系统的整体效率。这个压缩包...

    SharePoint WebService JS 调用脚本库

    5. **异步调用**:为了不影响用户界面的响应性,库可能支持异步调用Web服务,使得调用过程在后台执行。 6. **批量操作**:对于需要调用多个Web服务操作的情况,库可能提供批量执行的功能,提高性能。 7. **版本...

Global site tag (gtag.js) - Google Analytics