为什么在同步功能上实现异步?

Jab*_*ech 3 javascript asynchronous node.js

我是NodeJS的新手,并且发现使用异步函数有点困难。我想在这里找出好处。以下是我对异步功能的理解。

请您验证以下我的理解吗?

  1. 当要执行独立操作(来自主程序流)时,异步函数很好用。当主程序非常需要来自异步功能的数据/响应或将各种独立的异步功能互连时,使用异步功能是不理想的。
  2. 在主程序流程中依赖异步函数的输出结果是不好的。因为异步总是在主流程之后执行。因此,如果您需要在主流中执行某些功能,则最好将其定义为“同步”而不是“异步”。
  3. 调用独立异步函数时,通常的做法是使用Promise或回调函数来调用后续操作(异步函数)。
  4. 我仍然可以在Async函数中调用sync函数。但是,如果我从同步函数调用异步函数,则该程序可能无法按预期方式工作,因为异步函数只会在最后执行?

wei*_*nda 5

好吧,让我们逐一研究它。作为基础,请记住,Node.js是一个单线程进程,如果需要执行它,blocking processes例如读取文件(创建事件指针,读取文件句柄,设置文件路径,设置打开模式等),那会更好使用异步函数在同一页或线程s / pool的单独线程上执行。


1)当要执行独立操作(来自主程序流)时,可以使用异步功能。当主程序非常需要来自异步功能的数据/响应或将各种独立的异步功能互连时,使用异步功能是不理想的。

首先,main program由于Node.js世界中没有子程序(我不是在谈论模块之类的东西),因此我们不会将程序文件称为。

现在,当您说当需要立即输出时,不应该使用任何异步函数时,您实际上是对的。让我们来看下面的例子:

...
const data = readFile( 'fileName', ( data, output ) => {
    ...
} );
console.log( data ); // this might be null or undefined
Run Code Online (Sandbox Code Playgroud)

在上述情况下,我们将不使用异步功能(传统意义上)。但是,在ES6及更高版本中,我们得到了可爱的async/await范例:

const data = await readFile( 'filename' );
Run Code Online (Sandbox Code Playgroud)

await进行伪同步调用:其行为类似于一个async函数,但是会有一个暂停的线程等待输出。因此,在这里,您绝对正确!让我们继续前进。


2)依赖于主程序流程中async函数的输出结果是不好的。因为异步总是在主流程之后执行。因此,如果您需要在主流中执行某些功能,则最好将其定义为“同步”而不是“异步”。

在这里,您说它async在主流之后运行。现在,是不正确的。让我对线程评估和执行进行简单描述:

说,有两个sync函数A()B(),它们对应的线程是th__Ath__B,它们将如下所示:

th__a ---> th__b
Run Code Online (Sandbox Code Playgroud)

如果它们在顺序触发A()然后B()。它等待对第一个同步(或阻塞)过程的评估,然后执行第二个。显而易见,不是在整个执行结束之后。

但是,如果它们现在是异步函数,则它们将并行执行。说A()是一个同步函数,并且B()是一个异步函数,具有与上面相同的线程名,执行是这样的:

th__a     ----
- - th__b   ->
Run Code Online (Sandbox Code Playgroud)

其中,-代表时钟周期,->代表执行结束。我们可以看到它A()被触发,然后在新线程上B()被触发。

我想这很有道理。现在,再次返回,如果您需要在异步调用时立即使用它们,请使用await


3)调用独立异步函数时,通常的做法是使用Promise或回调函数来调用后续操作(异步函数)。

绝对。

说,我们定义一个函数sayHello()

const sayHello = () => {
    const P = Q.defer();

    // P.resolve(data);

    // or if there is an exception 
    // P.reject(error);

    return p.promise;
 };
Run Code Online (Sandbox Code Playgroud)

Q优秀的promise库在哪里。我们可以这样称呼它:

sayHello.then( ( data ) => {
    console.log( data ); // P.resolve(..) is working here since the promise was successful.
} ).catch( ( err ) => {
    console.log( err ); // P.reject(..) is working here since there was a problem.
} );
Run Code Online (Sandbox Code Playgroud)

或者您可以使用像这样的回叫fs.readFile(...)

fs.readFile( 'fileName', ( e, data ) => {
    if( e ) { return console.log( e ); } // error was handled
    // perform subsequent functions here with data
} );
Run Code Online (Sandbox Code Playgroud)

4)我仍然可以在Async函数中调用同步函数,但是如果从同步函数/操作中调用了异步函数,则程序可能无法按预期运行,因为异步函数只会在最后执行?

并不是的。参见点(2)。这与线程有关。不是静态过程。您可以在async函数中很好地调用sync函数,它将很好地工作。

当您读取文件时,说您想按\n或换行分割数据:

...
if( e ) { return console.log( e ); }
const dataLines = e.split( '\n' ); // this will work brilliantly 
...
Run Code Online (Sandbox Code Playgroud)

我希望一切都清楚了!:)