当前位置: 首页 > 面试题库 >

异步Javascript执行如何发生?什么时候不使用return语句?

贝凯
2023-03-14
问题内容

// synchronous Javascript
var result = db.get(‘select * from table1’);
console.log(‘I am syncronous’);

// asynchronous Javascript 
db.get('select * from table1', function(result){
    // do something with the result
});
console.log('I am asynchronous')

我知道在同步代码中,console.log()在从数据库中获取结果之后执行,而在异步代码中,console.log()在db.get()获取结果之前执行。

现在我的问题是,异步代码在后台如何执行?为什么非阻塞呢?

我搜索了Ecmascript 5标准,以了解异步代码的工作原理,但在整个标准中找不到异步一词。

从nodebeginner.org上,我还发现我们不应该使用return语句,因为它会阻塞事件循环。但是nodejs
api和第三方模块到处都包含return语句。那么什么时候应该使用return语句,什么时候不应该使用它?

有人可以对此有所启发吗?


问题答案:

首先,将函数作为参数传递就是告诉您正在调用的函数,希望将来某个时候调用该函数。确切的将来何时调用该函数取决于函数正在执行的操作的性质。

如果该函数正在进行一些联网,并且该函数配置为非阻塞或异步,则该函数将执行,将开始联网操作,并且您调用的函数将立即返回,而其余的内联javascript代码将在返回之后该功能将执行。如果从该函数返回一个值,则该值将立即返回,很早在调用作为参数传递的函数之前(联网操作尚未完成)。

同时,网络操作正在后台进行。它正在发送请求,侦听响应,然后收集响应。当网络请求完成并且已收集响应时,然后,然后您调用的原始函数将调用您作为参数传递的函数。这可能只是几毫秒后,也可能是几分钟后,这取决于网络操作完成的时间。

重要的是要理解,在您的示例中,db.get()函数调用已经完成很长时间了,执行完之后的代码也依次执行。尚未完成的是您作为参数传递给该函数的内部匿名函数。这一直保存在javascript函数闭包中,直到以后网络功能结束。

我认为,使很多人感到困惑的一件事是,匿名函数在您对db.get的调用中声明,并且似乎是该函数的一部分,并且当db.get()完成后似乎也会这样做,但这就是并非如此。如果以这种方式表示,则可能看起来不太像:

function getCompletionfunction(result) {
    // do something with the result of db.get
}

// asynchronous Javascript 
db.get('select * from table1', getCompletionFunction);

然后,也许更明显的是db.get将立即返回,并且getCompletionFunction将在将来的某个时间被调用。我不建议您以这种方式编写它,而只是显示此表单以说明实际情况。

这是一个值得理解的序列:

console.log("a");
db.get('select * from table1', function(result){
    console.log("b");
});
console.log("c");

您将在调试器控制台中看到以下内容:

a
c
b

“ a”首先发生。然后,db.get()开始其操作,然后立即返回。因此,“
c”接下来发生。然后,当db.get()操作实际上在将来的某个时间完成时,就会发生“ b”。



 类似资料:
  • asyncio文档明确指出,asyncio代码不应直接调用阻塞代码,还指定了使用异步代码运行阻塞代码的方法: 不应直接调用阻塞(CPU绑定)代码。例如,如果函数执行CPU密集型计算1秒,则所有并发异步IO任务和IO操作将延迟1秒。 可以使用执行器在不同的线程中甚至在不同的进程中运行任务,以避免事件循环阻塞OS线程。 然而,这个描述对于在什么时候应该使用执行器不是很具体。很明显,“1秒钟的CPU密集

  • 我在理解promise方面有一个(看似基本的)问题。首先是代码: 每个promise函数在添加到promise数组时被调用,而不是像我所想的那样调用Q.all。 我有什么不明白的? 如何在不立即调用所述promise的情况下将一系列promise排队?

  • 问题内容: 我怎么能说: 为什么函数调用中不需要括号,而最后一行呢? 问题答案: 是一个功能 调用该函数并产生该函数返回的任何值。 setTimeout的目的是在一段时间后运行代码。你需要的功能只是传递给它(这样的setTimeout可以自称在适当的时候函数),因为如果你将它传递给setTimeout的前调用的函数(用括号),将执行 现在 而不是1秒后,。

  • 问题内容: 奇怪的是: 似乎或多或少被定义为。通过这种方式很容易产生错误: 一些fname意外地以else块结尾。修复很简单,我们应该改用它,但是从表面上看,这似乎是一种不错的pythonic方式,并且比“正确”的方式更具可读性。 由于字符串是不可变的,所以为什么字符串错误是什么技术细节?什么时候进行身份检查更好,什么时候进行平等检查更好? 问题答案: 据我所知,检查对象身份是否相等。由于没有强制

  • 新的ES6箭头函数表示在某些情况下是隐式的: 表达式也是该函数的隐式返回值。 在什么情况下,我需要将与ES6箭头函数一起使用?

  • 我有一个并发HashMap,我在其中执行以下操作: 我的问题是——是否没有必要做额外的 检查synschronized块内部,以便其他线程不会初始化相同的hashmap值? 也许检查是必要的,但我做错了?我在做的事情似乎有点愚蠢,但我认为这是必要的。