【问题标题】:Does Javascript run lines of code in order? and finish processing then move on?Javascript 是否按顺序运行代码行?并完成处理然后继续?
【发布时间】:2016-03-09 17:51:56
【问题描述】:

我第一次尝试用 Javascript 编写一些代码,但我猜我在概念上没有得到一些东西!

以下代码对我来说可以正常工作:

var db = new alasql.Database("db");
db.exec('CREATE TABLE IF NOT EXISTS Myonetwo;');

var aaa = db.exec('select * into Myonetwo from json("http://localhost:8080/app1")',[],function(res){
    db.exec('select * from Myonetwo;',[],function(bbb){

            console.log(bbb.length);    
        });
});

但是这个是一样的,但不是内嵌函数的函数,不起作用。

var db = new alasql.Database("db");
db.exec('CREATE TABLE IF NOT EXISTS Myonetwo;');

var aaa = db.exec('select * into Myonetwo from json("http://localhost:8080/app1")');
var bbb = db.exec('select * from Myonetwo;');
console.log(bbb.length);

也将结果作为一个函数定义为所有 Javascript 的常用参数之一吗?

【问题讨论】:

    标签: javascript alasql


    【解决方案1】:

    这是因为exec 函数是异步的,所以在您的第二个示例中,bbb 分配行将在 aaa 分配行完成之前发生。

    这就是为什么exec 有一个回调函数作为它的最后一个参数。

    在您的第一个代码片段中,事件的时间线将类似于:

    • 第一次执行调用
    • 一段时间过去了...
    • 第一次执行回调发生
    • 第二个 exec 调用执行
    • 第二次执行回调发生

    在这种情况下,您知道第二次 exec 调用将在第一次 exec 调用之后发生。

    您的第二个代码片段的时间线将是:

    • 第一次执行调用
    • 第二次执行调用
    • 第一个或第二个 exec 调用完成(非确定性)
    • 第一个或第二个 exec 调用完成(非确定性)

    你可以看到这会对你的逻辑产生影响。

    这里有一篇很好的文章来了解更多关于异步编程的信息:https://blog.risingstack.com/asynchronous-javascript/

    【讨论】:

    • 正确吗?似乎(序数)第一个示例是异步的,而(序数)第二个示例是同步的。 docs 建议当函数exec 包含三个参数时将进行异步调用。
    • 感谢@franklin 指向那里。首先,我对异步一无所知。但是阅读你给我的链接,我想,这应该是同步的。然后我发现了这个link,似乎是因为那个 json() 部分我得到了异步
    • @Jonathan.Brink,感谢您的回答。有没有办法让我在那里等待或其他什么,所以我可以以某种方式回到同步模型?
    • @RoozbehG 我不确定这在这种情况下能有多大帮助,但你可能想看看 JavaScript 的“承诺”。
    【解决方案2】:

    是的,Javascript 会按顺序运行代码行。但也包含异步/延迟编程元素。

    概念可以看这里https://developer.mozilla.org/en/docs/Web/JavaScript/EventLoop

    归结为:

    console.log("a");
    console.log("b");    // output will be a, b, c
    console.log("c");
    
    // output will be a, b, c
    

    再来一次

    console.log("a");
    setTimeout(function(){
       concole.log("b");
    },0);
    console.log("c");
    
    //output will be a, c, b
    

    原因是打印“b”的代码在console.log("c")之前出现了两次,但之前确实没有两次执行。在第二种情况下,它通过 window.setTimeout(function, timeout) 函数在 EventLoop 中排队

    【讨论】:

      【解决方案3】:

      你可以重写代码:

      var db = new alasql.Database("db");
      var res = db.exec('CREATE TABLE IF NOT EXISTS Myonetwo;\
           select * into Myonetwo from json("http://localhost:8080/app1");\
           select * from Myonetwo;');
      console.log(res);
      

      在这种情况下,AlaSQL 将按顺序运行所有运算符(即使它们是异步的)并将它们保存到 res 变量中。

      其他情况需要用回调重写代码:

      var db = new alasql.Database("db");
      var res = db.exec('CREATE TABLE IF NOT EXISTS Myonetwo;');
      var res = db.exec('select * into Myonetwo from \
           json("http://localhost:8080/app1")',[],function(){
              var bbb = db.exec('select * from Myonetwo;');
              console.log(res);
      });
      

      在您的示例中,您只需要对第二行使用回调,因为 AlaSQL 中的 JSON() 函数是异步的。

      【讨论】:

        【解决方案4】:

        正如其他人所说,这是因为 javascript,或者在这种情况下,NodeJS 本质上是异步的。原因是委派 I/O 任务非常有效,因为它们的执行时间比普通任务要长得多。

        我觉得可以打个比方很好的解释:

        JavaScript 就像一个构建器。让我们叫他(或她)Bob

        场景 1 - 相当于第二个例子

        客户要求 Bob 盖房子。

        Bob 太忙了,无法独自完成这项工作,所以他问 Joe,一个 砖层来帮忙。

        开始砌砖。

        与此同时,Bob 要求水管工 Paul 在墙上安装管道。

        Pauls 人来铺设管道...... 等等 .. 没有 墙呢

        [故障]

        在 JavaScript 中,代码可能如下所示:

        Joe.layBricks()
        Paul.layPipes()
        

        这基本上就是您的第二个示例中发生的情况

        场景 2 - 相当于您的第一个示例

        鲍勃再试一次:

        客户要求Bob盖房子。

        Bob 让 Joe 铺砖。

        但这一次他告诉Joe,当他完成时他必须告诉 Paul(称为回调)他准备好了。

        保罗已经知道他需要做什么,但只需要知道他什么时候 可以的。

        好多了。工作会完成的。

        现在,Bob 甚至可以让画家 Pat 来给房子刷水了 以同样的方式完成。

        代码如下:

        Joe.layBricks(Paul.layPipes(Pat.paintWalls()))
        

        看起来很眼熟? (应该接近示例1)

        它是如何在其他语言中完成的

        Bob 很容易做的事情就是自己完成所有工作,但这不会非常有效或可扩展。这就是许多语言的工作方式。但是 NodeJS 有一个更好的方法,那就是回调发挥作用。

        其他高级语言允许您定义自己的线程。但它们非常复杂,可能难以理解和维护。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多