Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js中JavaScript/TypeScript中的异步/等待控制流_Javascript_Node.js_Typescript_Async Await_Control Flow - Fatal编程技术网

Node.js中JavaScript/TypeScript中的异步/等待控制流

Node.js中JavaScript/TypeScript中的异步/等待控制流,javascript,node.js,typescript,async-await,control-flow,Javascript,Node.js,Typescript,Async Await,Control Flow,上下文:我试图在TypeScript中实现一个基本的套接字池。我当前的实现只是一个套接字列表,其中附加了一个“可用/占用”枚举(可以是一个布尔值),允许我使用类似互斥的机制来确保每个套接字一次只发送/接收一条消息 我的理解是:Node.js处理“并行”操作的方式是“单线程异步” 我推断:对我来说,这意味着一次只有一个“控制指针”/“代码读取头”/“控制流位置”,因为只有一个线程。在我看来,readhead只有在调用“wait”时才会跳转到代码中的其他地方,而我正在“waiting”的承诺还无法解

上下文:我试图在TypeScript中实现一个基本的套接字池。我当前的实现只是一个套接字列表,其中附加了一个“可用/占用”枚举(可以是一个布尔值),允许我使用类似互斥的机制来确保每个套接字一次只发送/接收一条消息

我的理解是:Node.js处理“并行”操作的方式是“单线程异步”

我推断:对我来说,这意味着一次只有一个“控制指针”/“代码读取头”/“控制流位置”,因为只有一个线程。在我看来,readhead只有在调用“wait”时才会跳转到代码中的其他地方,而我正在“waiting”的承诺还无法解决。但我不确定事实是否如此

我想知道的是:“单线程异步”是否确保除了调用“wait”时,控制流位置在任何其他时间都不会发生跳转?或者是否有一些底层调度程序确实会在随机时刻导致任务之间的跳转,比如正常的多线程

我的问题:所有这些都是要问的,我是否需要一个纯互斥/比较和交换机制来确保我的类似互斥的可用/占用字段设置正确

考虑以下代码:

export enum TaskSocketStatus
{
    AVAILABLE,  //Alive and available
    OCCUPIED,   //Alive and running a task
}

export interface TaskSocket
{
    status:TaskSocketStatus;
    socket:CustomSocket;
}


export class Server //A gateway that acts like a client manager for an app needing to connect to another secure server
{
    private sockets:TaskSocket[];

    [...]

    private async Borrow_Socket():Promise<TaskSocket|null>
    {
        for (const socket of this.sockets)
        {
            if (!socket.socket.Is_Connected())
            {
                await this.Socket_Close(socket);
                continue;
            }
            if (socket.status === TaskSocketStatus.AVAILABLE)
            {
//This line is where things could go wrong if the control flow jumped to another task;
//ie, where I'd need a mutex or compare-and-swap before setting the status
                socket.status = TaskSocketStatus.OCCUPIED;
                return (socket);
            }
        }
        if (this.sockets.length < this.max_sockets)
        {
            const maybe_socket = await this.Socket_Create();
            if (maybe_socket.isError())
            {
                return null;
            }
 //Probably here as well
            maybe_socket.value.status = TaskSocketStatus.OCCUPIED;
            return maybe_socket.value;
        }
        return null;
    }

    [...]
 }

导出枚举TaskSocketStatus
{
可用,//活动且可用
已占用,//处于活动状态并正在运行任务
}
导出接口TaskSocket
{
状态:TaskSocketStatus;
套接字:自定义套接字;
}
导出类服务器//网关,其作用类似于需要连接到另一个安全服务器的应用程序的客户端管理器
{
专用套接字:TaskSocket[];
[...]
专用异步借用\u套接字():承诺
{
for(此.sockets的常量套接字)
{
如果(!socket.socket.Is_Connected())
{
等待。插座\关闭(插座);
继续;
}
if(socket.status==TaskSocketStatus.AVAILABLE)
{
//如果控制流跳转到另一个任务,这一行可能会出错;
//例如,在设置状态之前,我需要一个互斥或比较和交换
socket.status=TaskSocketStatus.occulated;
返回(插座);
}
}
if(this.sockets.length
我希望避免的问题是,由于竞争条件,两个不同的“SendMessage”任务借用同一个套接字。也许这是不必要的担心,但我想确定一下,因为这是一个潜在的问题,当服务器已经投入生产时,我真的不想面对它


谢谢你的帮助

因此,调用
await
时,不存在到另一个操作的控制流。当Javascript的运行部分返回到事件循环时,事件循环就可以为下一个等待的事件提供服务。已解析的承诺也通过事件循环(一个特殊队列,但仍在事件循环中)工作

所以,当您点击
wait
时,它不会立即将控件跳转到其他地方。它暂停该函数的进一步执行,然后使该函数立即返回一个承诺,控制继续,并将一个承诺返回给函数的调用方。调用方的代码在收到该承诺后继续执行。只有当调用者或调用者的调用者或调用者的调用者(取决于调用堆栈的深度)从启动整个执行链的任何事件返回事件循环时,事件循环才有机会服务下一个事件并启动新的执行链

一段时间后,当连接到原始
wait
的基础异步操作完成时,它将向事件队列插入一个事件。当其他Javascript执行将控制权返回到事件循环,并且此事件到达事件队列的开始时,它将被执行,并将解析
wait
正在等待的承诺。只有在
等待
之后,函数中的代码才有机会运行。当包含
await
async
函数最终完成其内部执行时,当第一个
await
被命中时,最初从
async
函数返回的承诺将被解析,并且调用方将被通知它返回的承诺已被解析(假设它使用了
等待
然后()

因此,流不会从一个地方跳到另一个地方。Javascript执行的当前线程将控制返回到事件循环(通过返回并展开其调用堆栈)然后,事件循环可以为下一个等待事件提供服务,并启动一个新的执行链。只有当该执行链完成并返回时,事件循环才能获取下一个事件并启动另一个执行链。这样,一次只运行一个调用堆栈帧

在您的代码中,我并不完全了解您所关心的内容。Javascript中没有先发制人的切换。如果您的函数执行了
等待
,那么它的执行将在该点暂停,其他代码可以在承诺得到解决之前运行,并在
等待
之后继续执行。但是,没有先发制人mptive切换,可以更改上下文并在此线程中运行其他代码,而无需您的代码调用某个异步操作