zoukankan      html  css  js  c++  java
  • 互联网我来了 -- 2. js中"异步/堵塞"等概念的简析

    一、什么是”异步非堵塞式”?

    这个名字听起来非常恶心难懂,但假设以 买内裤 这件事情来比喻运行程序的话就非常easy理解“异步非堵塞式”的涵义了。

    比如你是一个CPU的线程。你须要去运行一段 买内裤的程序, 你所需运行的步骤大致例如以下,

    1. 到一个商店里问老板, 你们店里还有没有nb牌内裤?
    2. 买到内裤。穿上
    3. 去小卖店买点火腿回家喂狗

    这时候。你作为一个线程,你可能会遇到几种状况或选择。

    1. 店里面没货了。老板一直不答应你(堵塞你),你也一直等着(同步),第三天有货了才告诉你有了。你赶紧拿到穿上。再去买火腿 – [同步堵塞模式]
    2. 老板立即告诉你“没货了”(不堵塞你),然后你每天去店里问一声,直到有货了赶紧穿上,再去买东西喂狗 – [同步非堵塞]
    3. 你让老板有货了打电话叫你过来取。老板说“好的”(非堵塞),然后你就先去买东西喂狗了,过了两天老板叫你过去,你才拿到内裤并穿上 – [异步非堵塞]
    4. 你让老板有货了打电话叫你过来取, 老板又没答应你(堵塞), 然后你本来打算去先去买火腿的(异步),这时候也没法去了。

       – [异步堵塞]

    非常明显。第三种方法是最聪明,前两种方法都略显效率低下。所以依据我们的理解,

    同步或非同步,表明着是否须要将整个流程顺序地完毕

    堵塞或非堵塞。意味着你调用的函数会不会立马告诉你结果

    二、在js中的堵塞与同异步

    你有一个函数和一段程序。

    2.1 js中的同步堵塞

    // 这是一个堵塞式函数, 将一个文件拷贝到还有一个文件上
    function copyBigFile(afile, bfile){
        var result = copyFileSync(afile,bfile);
        return result;
    }

    调用这个”copyBigFile()”函数。将一个大文件拷贝到还有一个文件上。将耗时1小时。意味着这个函数的将在一个小时之后返回。

    //这是一段程序
    console.log("start copying ... ");    
    var a = copyBigFile('A.txt', 'B.txt');  //这行程序将耗时1小时
    console.log("Finished");   // 这行程序将在一小时后运行
    console.log("处理一下别的事情");  // 这行程序将在一小时后运行
    console.log("Hello World, 整个程序已载入完毕,请享用"); // 这行程序将在一小时后运行

    以上的程序就是一个同步堵塞的样例。由于copyFileSync函数返回值的过程须要漫长的时间。所以线程也无法继续运行下去,仅仅能等待。

    2.2 js中的同步非堵塞

    // 这是一个非堵塞式函数
    // 假设复制已完毕。则返回 true, 假设未完毕则返回 false
    function copyBigFile(afile,bfile){
        var copying = copyFileAsync(afile, bfile);
        var isFinished = !copying;
        return !isFinished; 
    }

    调用这个函数将立马返回结果,然后你的程序就能够写成

    console.log("start copying ... ");    
    while( a = copyBigFile('A.txt', 'B.txt')){
      console.log("在这之间还能够处理别的事情");
    } ;  
    console.log("Finished");   // 这行程序将在一小时后运行
    console.log("Hello World, 整个程序已载入完毕,请享用"); // 这行程序将在一小时后运行

    一个非堵塞式的函数,给你的编程带来了很多其它的便利,你能够在长IO操作的同一时候。写点其它的程序,提高效率。运行结果例如以下

    start copying ...
    在这之间还能够处理别的事情
    在这之间还能够处理别的事情
    在这之间还能够处理别的事情
    ...
    Finished
    Hello World, 整个程序已载入完毕。请享用

    2.3 js中的异步非堵塞

    我们看到,一个非堵塞式的函数能给我们编程带来很多灵活性。我们喜欢非堵塞式的函数。
    可是。又能够看到同步的程序须要在一个循环中轮询结果,循环里面的程序会被运行好多遍,所以并不好控制来写一些正常的程序,非常难再利用起来。
    所以我们须要一种更为合理的方式对非堵塞式的函数进行利用。
    也就是我不会主动地去询问结果,而是当你有了结果的时候再来通知我。
    // 这是一个非堵塞式函数
    // 假设复制已完毕,则返回 true, 假设未完毕则返回 false

    //非堵塞式的有异步通知能力的函数
    //下面不须要看懂,仅仅用知道这个函数会在完毕copy操作之后,运行success
    function copyBigFile(afile,bfile, callback){
        var copying = copyFileAsync(afile, bfile, function(){ callback();});
        var isFinished = !copying;
        return !isFinished; 
    }

    这个函数不同于上一个同步非堵塞函数的地方在于。它具有通知功能,也就是说,它能够在完毕操作之后主动地通知程序,“我完毕了”。于是有程序例如以下,

    console.log("start copying ... ");    
    copyBigFile("A.txt","B.txt", function(){
              console.log("Finished");   //一个小时后被运行
              console.log("Hello World, 整个程序已载入完毕,请享用"); //一个小时后被运行
              })
    console.log("干别的事情"); 
    console.log("做一些别的处理"); 
    

    程序在调用copyBigFile函数之后,能够立即获得返回值,线程没有被堵塞住,于是还能够去干些别的事情。然后当copyBigFile完毕之后。会运行指定的函数。

    所以程序的输出应为,

    start copying ...
    干别的事情
    做一些别的处理
    Finished
    Hello World, 整个程序已载入完毕。请享用

    在这样的情况下。程序更easy控制,流程更为清晰。

    一些“别的事情”能够在函数还未通知之前进行处理,充分地提高了线程的利用效率。

    三、提升

    在以上的程序中。我们的程序须要拷贝一个巨大的文件。事实上复制文件这个过程是留给系统的IO调用进行完毕的。而我们的线程并不须要去处理拷贝的细节。
    所以通过非堵塞式的函数,我们能够 有可能 利用线程资源去干一下别的事情。
    而通过异步调用方式。能使得程序流程 更easy控制,更有效率地利用线程资源。

    而js是通过传递函数实现异步的。(还有能够通过promise的方式来实现异步…)

  • 相关阅读:
    bug终结者 团队作业第二周
    dropdownlist绑定数据
    virtual与vmware
    后台控制输出table(有数据库)
    label 绑定数据
    flash不能显示中文
    dataset 多表查询
    MVC3 Razor视图引擎基础语法 [转]
    CreateAlias()与setFetchMode() [转 李丽芬]
    Linq Like [转 韩天伟]
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5315244.html
Copyright © 2011-2022 走看看