4

我第一次尝试用 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 的参数之一的函数?

4

4 回答 4

3

是的,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 中排队

于 2016-03-09T18:00:44.490 回答
3

这是因为该exec函数是异步的,因此在您的第二个示例中,bbb赋值行将在aaa赋值行完成之前发生。

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

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

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

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

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

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

您可以看到这将影响您的逻辑。

这是一篇了解更多关于异步编程的好文章:https ://blog.risingstack.com/asynchronous-javascript/

于 2016-03-09T17:54:14.803 回答
2

你可以重写代码:

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() 函数是异步的。

于 2016-03-09T21:20:38.590 回答
2

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

我认为可以用一个类比很好地解释:

JavaScript 就像一个构建器。让我们称他(或她)鲍勃

场景 1 - 相当于第二个有问题的例子

客户要求鲍勃盖房子。

鲍勃太忙了,无法独自完成工作,所以他请砖瓦工乔帮忙。

开始砌砖。

与此同时,鲍勃让水管工保罗在墙上安装管道。

保罗的人要铺设管道......坚持下去..还没有墙

[故障]

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

Joe.layBricks()
Paul.layPipes()

这基本上就是你的第二个例子中发生的事情

场景 2 - 相当于你的第一个例子

鲍勃再试一次:

客户要求鲍勃盖房子。

鲍勃让乔铺砖。

但是这一次他告诉,当他完成时,他必须告诉保罗(称为回调)他已经准备好了。

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

好多了。工作会完成的。

现在,鲍勃甚至可以让油漆工帕特在管道完成后以同样的方式粉刷房子。

代码如下所示:

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

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

它是如何用其他语言完成的

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

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

于 2016-03-09T18:36:25.910 回答