我是NodeJS新手,我发现使用异步函数有点困难。我想找出这里的好处。下面是我对异步函数的理解。
,请您验证我在下面的每一项理解?
发布于 2018-09-11 05:33:04
好吧,让我们一片一片地研究。作为一个基础,请记住Node.js是一个单线程进程,如果它需要执行blocking processes,例如读取文件(创建一个事件指针、读取文件句柄、设置文件路径、设置打开模式等)。最好使用异步函数,它在同一页的单独线程或线程的/池上执行。
1)当独立操作(来自主程序流)被执行时,异步函数可以很好地使用。当主程序非常需要来自异步函数的数据/响应或各种独立的异步函数互连时,使用异步函数是不理想的。
首先,我们不会将程序文件称为main program,因为在Node.js世界中没有子程序(我是而不是,谈论模块等)。
现在,当您说在迫切需要输出时不应该使用任何异步函数时,实际上是正确的。让我们以下面的例子为例:
...
const data = readFile( 'fileName', ( data, output ) => {
...
} );
console.log( data ); // this might be null or undefined在上述情况下,我们将不使用异步函数(在传统意义上)。然而,在ES6和更高版本中,我们得到了可爱的async/await范例:
const data = await readFile( 'filename' );await使调用伪同步:它的行为类似于一个async函数,但是会有一个暂停的线程等待输出。所以,在这里,你是绝对正确的!让我们继续吧。
2)在主程序流中依赖异步函数输出的结果是不好的。因为异步总是在主流之后执行。因此,如果需要在主流中执行某些函数,最好将其定义为同步的,而不是异步的。
在这里,您说async在主流之后运行。现在,认为是不正确的。让我画一个线程评估和执行的简单图片:
比方说,有两个sync函数A()和B(),它们对应的线程是th__A和th__B,它们将如下所示:
th__a ---> th__b如果它们是按A()顺序发射的,那么B()。它等待第一个同步(或阻塞)进程的计算,然后执行第二个进程。很明显,这并不是在整个执行结束之后。
但是,如果它们现在是异步函数,它们将并行执行。假设A()是一个同步函数,而B()是一个异步函数,具有与上面相同的线程名,执行如下所示:
th__a ----
- - th__b ->其中-代表时钟周期,->代表执行的结束。我们可以看到,A()被触发,然后,在一个新线程上,B()被触发。
我想这是有道理的。现在,再次返回,如果您需要立即使用它们,同时作为异步调用,则使用await。
3)调用独立异步函数时,通常使用许诺或回调调用后续操作(异步函数)。
绝对一点儿没错。
比如说,我们定义了一个函数sayHello()
const sayHello = () => {
const P = Q.defer();
// P.resolve(data);
// or if there is an exception
// P.reject(error);
return p.promise;
};其中Q是优秀的承诺库。我们可以称之为:
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.
} );或者您也可以像fs.readFile(...)那样使用回调
fs.readFile( 'fileName', ( e, data ) => {
if( e ) { return console.log( e ); } // error was handled
// perform subsequent functions here with data
} );4)我仍然可以在异步函数中调用同步函数,但是如果从同步函数/操作调用异步函数,程序可能无法按预期工作,因为异步函数将只在最后执行?
不怎么有意思。请参阅第(2)点。是关于线的。不是静态过程。您可以很好地调用异步函数中的同步函数,它将完美地工作。
当您读取文件时,假设您希望通过\n或新行拆分数据:
...
if( e ) { return console.log( e ); }
const dataLines = e.split( '\n' ); // this will work brilliantly
...我希望这一切都清楚了!
发布于 2018-09-11 04:55:37
发布于 2018-09-11 14:09:26
在javascript/node应用程序中实际使用异步功能是在处理网络请求和/或I/O操作(或可能需要很长时间的事情)时发挥作用的。
--网络呼叫示例
以聊天应用程序为例。客户端(您)向某人发送消息。该消息被发送到服务器或直接发送给收件人(P2p),以便根据通信模型进行进一步处理。您还希望向其他人发送另一条消息;person B。但是,如果不异步处理请求,客户端(您)可能必须等待一段不确定的时间;取决于您的网络速度、收件人的网络速度、网络超时时间或任何其他负责因素。
考虑到你必须等待两个单位的时间才能完成你的请求。
time: 1 2 3 4 5
action: SendToA(message) waitA waitA ResponseFromA SendToB(message)但是如果相同的请求是异步的。您发送由客户机(用于p2p通信)或客户机和服务器(用于客户机/服务器)通信异步处理的请求。这就是浏览器中实际发生的情况。浏览器异步处理请求,以便在等待请求完成时,浏览器代码的任何其他部分都不会被卡住。
time: 1 2 3 4 5
action: SendToA(message) waitA/SendToB(message) waitA/waitB ResponseFromA ResponseFromB因此,在同步情况下,只有一个请求在5个时间单元内成功,而在异步情况下,只有两个请求在5个时间单元内成功。
注意到:实际的实现可能以时间为单位推迟,这只是实际发生的事情的一般想法。
I/O读写示例
I/O读/写非常类似于网络调用;也就是说,完成它需要时间。假设您的应用程序有两个表,从两个不同的文件中读取并填充每个表。如果同步处理这两个请求,则总体执行会出现大量延迟,而异步则会有所帮助。
同步:
time: 1 2 3 4 5
action: ReadFromFileA(message) waitA waitA ResponseFromA ReadFromFileB(message)对于异步:
time: 1 2 3 4 5
action: ReadFromFileA() ReadFromFileB() waitA/waitB ResponseFromA ResponseFromB这是对异步调用/函数可以做什么的一个非常普遍的解释。然而,异步并不总是所要做的事情。正如您在问题中提到的,有时确实需要同步调用/函数。
打印是一个非常特殊的操作,必须是同步的。不能异步打印两份文件。
相关的函数也必须是同步的。
所有这一切,异步是一个非常强大的功能,如果使用correctly.There几乎总是可能的异步性在一个实时应用程序。如果你的应用程序不使用它,你的用户可能会抱怨你的应用程序中的坏用户。
https://stackoverflow.com/questions/52268715
复制相似问题