JavaScript:异步函数

JavaScript: asynchronous function

本文关键字:函数 异步 JavaScript      更新时间:2023-12-04

我试图理解异步代码的概念,所以我生成了以下代码:

"use strict";
var fs = require("fs");
var buf = new Buffer(1024);
console.log("Global Start");
console.log("+++ Async open - truncate - close: open file2 called");
fs.open("file2.txt", "r+", function (err, fd) {
  console.log(" Global + 1 Start");
  if (err) {
    return console.error(err);
  }
  console.log(" +++ Async file2 opened successfully!");
  // Truncate the opened file.
  console.log(" +++ Async open - truncate - close: truncate file2 called");
  fs.ftruncate(fd, 10, function (err) {
    console.log("       Global + 2 Start");
    if (err) {
      console.log(err);
    }
    console.log("       +++ truncate file2 successfully!");
    console.log("       +++ Async open - truncate - close: read file2 called");
    fs.read(fd, buf, 0, buf.length, 0, function (err, bytes) {
      console.log("         Global + 3 Start");
      if (err) {
        console.log(err);
      }
      // Print only read bytes to avoid junk.
      if (bytes > 0) {
        console.log("           Global + 3 +++ truncate read: '" + buf.slice(0, bytes).toString() + "'");
      }
      // Close the opened file.
      console.log("         Global + 3 +++ truncate - open - close: close file2 called");
      fs.close(fd, function (err) {
        console.log("               Global + 4 Start");
        if (err) {
          console.log(err);
        }
        console.log("               Global + 4 ++++++++++++++++++++ Async open - truncate - close file2 + closed ++++++++++++++++++++");
        console.log("               Global + 4 End");
      });
      console.log("         Global + 3 End");
    });
    console.log("       Global + 2 End");
  });
  console.log(" Global + 1 End");
});
console.log("Global End");

它创建了以下输出。

Global Start
+++ Async open - truncate - close: open file2 called
Global End
        Global + 1 Start
        +++ Async file2 opened successfully!
        +++ Async open - truncate - close: truncate file2 called
        Global + 1 End
                Global + 2 Start
                +++ truncate file2 successfully!
                +++ Async open - truncate - close: read file2 called
                Global + 2 End
                        Global + 3 Start
                        Global + 3 +++ truncate read: 'This is a '
                        Global + 3 +++ truncate - open - close: close file2 called
                        Global + 3 End
                                Global + 4 Start
                                Global + 4 ++++++++++++++++++++ Async open - truncate - close file2 + closed ++++++++++++++++++++
                                Global + 4 End

以下是我对它的看法:


  1. 全球范围:"全球启动"
  2. 使用回调函数调用fs.open,该函数将在fs.open完成后执行
  3. fs.open开始工作,而不是等待结果,而是执行全局级别的下一个任务,即"全局结束"。

  4. 现在fs.open完成,回调函数被调用。我们进入全球+1范围。

  5. 全球+1范围:"全球+1启动"

  6. 使用回调函数调用fs.ftruncate,当fs.ftrucute完成时执行该函数

  7. fs.ftruncate开始工作,当它工作时,Global+1作用域上的剩余代码将被执行,即"Global+1 End"。

  8. fs.ftruncate完成后,将调用它的回调函数。

全球+3和全球+4遵循相同的模式。


所以我的问题是;

我对代码中发生的事情的描述正确吗?

在我看来,异步代码是从最外层的括号(Global作用域)到最内层的括号(Global+4作用域)执行的。它不是从最内层到外层(就像数学中一样),也不是从顶层到底层(就像同步代码一样)。这是正确的吗?

如果全局作用域上的一个函数完成并在全局作用域中的其他代码完成之前执行其回调函数,会发生什么情况。回调会等待全局代码完成吗?

如果用不同的文件执行相同的代码,处理不同的文件需要不同的时间,那么输出的结果会有不同的顺序吗?

您对此有很好的理解。关于您的问题:

  1. "在我看来,异步代码是从最外层的括号(全局范围)到最内层的括号执行的"

异步调用将像执行任何其他命令一样执行,但不会等待结果,而是执行下面的下一个命令。下一个命令是异步回调后的直接一行,除非有某种函数调用

  1. "回调将等待全局代码完成吗?"

全局作用域变量不会等待异步调用,反之亦然。代码将运行,稍后依赖于异步调用中的变量的一些代码可能会也可能不会获得这些变量的更新版本。这取决于异步调用是否按时完成。

  1. "如果用不同的文件执行相同的代码,而处理不同的文件需要不同的时间,那么输出的结果会有不同的顺序吗?"

同样,代码的执行顺序取决于异步调用的速度。代码将始终以相同的顺序读取。为了防止击败异步调用,你应该确保所有依赖异步调用的JS都进入回调,因为它会等到异步完成。

我相信我已经回答了你所有的问题,如果我遗漏了什么,任何人都可以评论。