Saltar al contenido

TimeoutException: el proceso de CLI de Angular no comenzó a escuchar solicitudes dentro del período de tiempo de espera de 0 segundos

Solución:

TL; DR

Lamentablemente, el problema parece estar relacionado con algunos cambios en la forma en que Angular CLI inicia la parte angular de la aplicación. Según este problema:

https://github.com/dotnet/aspnetcore/issues/17277

Las soluciones propuestas son establecer el progreso: verdadero en angular.json o realizar un eco simple antes de ng serve (https://github.com/dotnet/aspnetcore/issues/17277#issuecomment-562433864).

Respuesta completa

Cavé la base del código principal de asp.net (https://github.com/dotnet/aspnetcore), mirando cómo la plantilla Angular inicia la aplicación Angular.

El motor central que inicia el servidor angular está representado por dos clases: AngularCliMiddleware (https://git.io/JvlaL) y NodeScriptRunner (https://git.io/Jvlaq).

En AngularCliMiddleware encontramos este código (eliminé los comentarios originales y agregué algunos propios para explicar un par de cosas):

public static void Attach(ISpaBuilder spaBuilder, string npmScriptName)
{
    var sourcePath = spaBuilder.Options.SourcePath;
    if (string.IsNullOrEmpty(sourcePath))
    {
        throw new ArgumentException("Cannot be null or empty", nameof(sourcePath));
    }

    if (string.IsNullOrEmpty(npmScriptName))
    {
        throw new ArgumentException("Cannot be null or empty", nameof(npmScriptName));
    }

    // Start Angular CLI and attach to middleware pipeline
    var appBuilder = spaBuilder.ApplicationBuilder;
    var logger = LoggerFinder.GetOrCreateLogger(appBuilder, LogCategoryName);
    var angularCliServerInfoTask = StartAngularCliServerAsync(sourcePath, npmScriptName, logger);

    var targetUriTask = angularCliServerInfoTask.ContinueWith(
        task => new UriBuilder("http", "localhost", task.Result.Port).Uri);

    SpaProxyingExtensions.UseProxyToSpaDevelopmentServer(spaBuilder, () =>
    {
        var timeout = spaBuilder.Options.StartupTimeout;
        return targetUriTask.WithTimeout(timeout,
            $"The Angular CLI process did not start listening for requests " +

            // === NOTE THIS LINE, THAT CARRIES THE "0 seconds" BUG!!!
            $"within the timeout period of {timeout.Seconds} seconds. " + 

            $"Check the log output for error information.");
    });
}

private static async Task<AngularCliServerInfo> StartAngularCliServerAsync(
    string sourcePath, string npmScriptName, ILogger logger)
{
    var portNumber = TcpPortFinder.FindAvailablePort();
    logger.LogInformation($"Starting @angular/cli on port {portNumber}...");

    var npmScriptRunner = new NpmScriptRunner(
        sourcePath, npmScriptName, $"--port {portNumber}", null);
    npmScriptRunner.AttachToLogger(logger);

    Match openBrowserLine;
    using (var stdErrReader = new EventedStreamStringReader(npmScriptRunner.StdErr))
    {
        try
        {
            // THIS LINE: awaits for the angular server to output
            // the 'open your browser...' string to stdout stream
            openBrowserLine = await npmScriptRunner.StdOut.WaitForMatch(
                new Regex("open your browser on (http\S+)", RegexOptions.None, RegexMatchTimeout));
        }
        catch (EndOfStreamException ex)
        {
            throw new InvalidOperationException(
                $"The NPM script '{npmScriptName}' exited without indicating that the " +
                $"Angular CLI was listening for requests. The error output was: " +
                $"{stdErrReader.ReadAsString()}", ex);
        }
    }

    var uri = new Uri(openBrowserLine.Groups[1].Value);
    var serverInfo = new AngularCliServerInfo { Port = uri.Port };

    await WaitForAngularCliServerToAcceptRequests(uri);

    return serverInfo;
}

Como puede ver, el StartAngularCliServerAsync El método crea un nuevo NpmScriptRunner , que es un envoltorio alrededor de una llamada al método Process.Start, básicamente, adjunta el registrador y luego espera a que StdOut del proceso emita algo que coincida con “abra su navegador en httpSOMETHING …”.

Lo divertido es Esto debería funcionar!

Si ejecuta ng serve (o npm run start) en la carpeta ClientApp, una vez que el servidor se inicia, aún emite la salida “abra su navegador en http …”.

Si dotnet ejecuta la aplicación, el servidor de nodos realmente se inicia, solo habilite todos los registros en el modo de depuración, busque la línea “Iniciando @ angular / cli en el puerto …” e intente visitar localhost en ese puerto, verá que su aplicación angular ESTÁ ejecutándose.

El problema es que, por alguna razón, StdOut ya no recibe la línea “abrir su navegador en”, ni está escrita por el registrador … parece que de alguna manera esa línea de salida particular de ng serve se retiene, como si fuera ya no se envía en el flujo de salida de Stardard. El método WaitForMatch alcanza su tiempo de espera después de 5 segundos y se captura del código del método de extensión WithTimeout, que genera el mensaje (con errores) “… 0 segundos …”.

Por lo que pude ver, una vez que dotnet ejecuta su aplicación, se genera una serie de procesos en secuencia, pero no pude notar ninguna diferencia en las líneas de comando de Angular 8 a Angular 9.

Mi teoría es que se ha cambiado algo en Angular CLI que evita que esa línea se envíe en stdout, por lo que el proxy .net no la detecta y no puede detectar cuándo se inicia el servidor angular.

Según este problema:

https://github.com/dotnet/aspnetcore/issues/17277

Las soluciones propuestas son establecer el progreso: verdadero en angular.json o realizar un eco simple antes de ng serve (https://github.com/dotnet/aspnetcore/issues/17277#issuecomment-562433864).

Lo resolví cambiando:

"scripts": {   
        "start": "ng serve",

para:

 "scripts": {   
        "start": "echo Starting... && ng serve",

en package.json

Aquí esta lo que hice

de Fairlie Agile, comentó esta línea en main.ts

export { renderModule, renderModuleFactory } from '@angular/platform-server';

De Claudio Valerio En angular.json, configure

"progress": true,

Ahora puedo ejecutar la aplicación haciendo clic en F5 / Ejecutar IIS Express

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *