Javascript异步执行机制

Javascript异步执行机制,javascript,ecmascript-6,rxjs,Javascript,Ecmascript 6,Rxjs,有人能解释一下javascript异步行为背后的机制吗,特别是当涉及到.subscribe()时,或者提供一个链接来帮助我理解引擎盖下到底发生了什么 一切看起来都是单线程的,然后我遇到了多线程或多线程的情况,因为我仍然无法摆脱被愚弄的感觉 在我调用.subscribe()之前,每一条指令似乎都完全同步运行。然后,突然发生了一些事情——它立即返回,并且不知何故,下一个外部函数运行,即使订阅代码尚未运行。对我来说,这感觉是异步的,浏览器如何保持事情的直线性?如果不是线程,有人能解释一下允许这种情况发

有人能解释一下javascript异步行为背后的机制吗,特别是当涉及到.subscribe()时,或者提供一个链接来帮助我理解引擎盖下到底发生了什么

一切看起来都是单线程的,然后我遇到了多线程或多线程的情况,因为我仍然无法摆脱被愚弄的感觉

在我调用.subscribe()之前,每一条指令似乎都完全同步运行。然后,突然发生了一些事情——它立即返回,并且不知何故,下一个外部函数运行,即使订阅代码尚未运行。对我来说,这感觉是异步的,浏览器如何保持事情的直线性?如果不是线程,有人能解释一下允许这种情况发生的机制吗


我还注意到调试单步执行时发生了一些事情,我不能单步执行回调,我只能在回调中放置一个断点。我应该以什么样的顺序期望事情发生?

在“JavaScript事件循环”中搜索文章或视频。你会发现很多。可能会经历其中的一些,它将开始有意义(特别是它的单线程方面)

我通过快速搜索找到了这个,它做了一个很好的高级演练

JavaScript单线程的主要影响是,在另一个线程上执行代码时,您的代码不会被预先中断

看起来有些代码被跳过了,但仔细观察语法会发现,被“跳过”的只是一个回调函数或闭包,在将来某个时候调用(当它被放入事件队列并以单线程方式处理时)

小心,遵循嵌套回调可能很棘手


可能还会研究Promises和async/await(“只是事件循环的语法方便,但确实有助于代码的可读性”)

您的Javascript本身运行单线程,除非您谈论的是WebWorkers(在浏览器中)或WorkerThreads(在nodejs中)

但是,在Javascript中调用的许多函数或启动的操作可以与Javascript的单线程特性分开运行。例如,网络都是非阻塞和异步的。这意味着,当您在nodejs的
http.get()
浏览器中调用
fetch()
时,您正在启动一个http请求,然后发出该请求和接收响应的机制独立于Javascript完成。以下是一些示例步骤:

  • 在浏览器中调用
    fetch()
    ,向其他主机发出http请求
  • fetch后面的代码发送http请求,然后立即返回
  • Javascript将继续执行(在
    fetch()
    调用将立即执行代码行中的所有内容)
  • 稍后,来自
    fetch()
    调用的响应返回网络接口独立于Javascript的单个线程,它可以看到有从http响应读取的传入数据。当该代码收集了http响应时,它会将一个事件插入Javascript事件队列
  • 当Javascript的单个线程完成执行它正在执行的任何事件时,它会检查事件队列以查看是否还有其他事情要做。在某个时候,它会找到表示上一次
    fetch()完成的事件
    调用,将有一个回调函数与该事件关联。它将调用该回调函数,该回调函数将解析与
    fetch()
    调用关联的承诺,该调用将在
    中生成您自己的Javascript。然后()
    handler,用于运行该承诺,您的Javascript将显示您等待的http响应
  • 因为这些非阻塞、异步操作(如网络、计时器、磁盘I/O等)所有这些都以相同的方式工作,并且可以独立于JavaScript执行,它们可以并行运行与您的JavaScript执行,其中许多可以同时在您的JavaScript执行其他事情的同时运行。这可能有时会出现多个线程,并且可能有一些本机代码线程PAR。尽管Javascript仍然只有一个线程(只要我们不是在讨论WebWorkers或WorkerThreads),但仍有一些问题需要解决

    然后,这些异步操作的完成通过事件队列与Javascript的单个线程同步。当它们完成时,它们将一个事件放入事件队列中,当Javascript的单个线程完成上一个操作时,它将从事件队列中获取下一个事件并对其进行处理(调用Javascript回调)

    我还注意到调试单步执行时发生了一些事情,我不能单步执行回调,我只能在回调中放置一个断点。我应该以什么样的顺序期望事情发生

    这是因为回调不是同步调用的。当您跨过传递回调的函数时,它会执行该函数并返回。您的回调尚未调用。因此,调试器完全按照您的要求执行。它执行了该函数并返回了该函数。回调尚未执行。哟如果你想看到异步回调执行,你需要在其中放置一个断点,这样当它在将来某个时候被调用时,调试器就会停在那里,让你更进一步。这是调试异步事物的一个复杂过程,但你会在一段时间后习惯它

    一切看起来都是单线程的,然后我遇到了多线程的情况,或者看起来是多线程的,因为
    console.log("starting...");
    fetch(host1).then(result1 => { console.log(result1)});
    fetch(host2).then(result2 => { console.log(result2)});
    fetch(host3).then(result3 => { console.log(result3)});
    fetch(host4).then(result4 => { console.log(result4)});
    console.log("everything running...");
    
    starting...
    everything running...
    result1
    result2
    result3
    result4