Принудительно Javascript / Node ждать завершения обслуживания - PullRequest
1 голос
/ 26 марта 2020

Я пытаюсь позвонить в службу и создать объект с полученным значением. Если бы я знал, что делаю, я бы тоже справился с ошибками, но не знаю как. К сожалению, код начинает сервисный вызов, а затем возвращается к оператору, следующему за сервисом, до того, как сервисный вызов завершится.

Мне все равно, насколько не современно, не круто или что бы то ни было, я хочу этого введите и ждите , чтобы служба успешно работала или не работала. Все, что я делаю в приложении, зависит от успеха этого сервиса.

Я пытался установить точки останова и добавить операторы журналирования.

import { Injectable, Injector } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { UUID } from 'angular2-uuid';
import { Constants } from './constants';

@Injectable()
export class AppConfigService {

    private constants = null;

    constructor (private injector: Injector) { }

    loadAppConfig() {
        let http = this.injector.get(HttpClient);
        /*
        return http.get('/assets/app-config.json')
        .toPromise()
        .then(data => {
            this.appConfig = data;
        })
        */
        if(this.constants != null) {
            console.log('@@WOODSMAN environmentData is not null');
            console.log('@@WOODSMAN lazy loaded environmentData already is '+JSON.stringify(this.constants));    
        } else {
            console.log('@@WOODSMAN environmentData is null');   

            let headerValues = new HttpHeaders()
                .set('Accept-Encoding', 'application/json; charset=UTF-8')
                .set('Content-Type', 'application/json; charset=UTF-8')
                .set('SC_TRACE_ID', UUID.UUID());
            let httpOptions = {
                headers: headerValues
            };
            console.log('@@WOODSMAN: Waiting for environment info from service call');

            let appConfig = http.post("/proxy/report/getEnvironment", "",httpOptions)
                .toPromise().then(data => { 
                this.setConstants(data);
            });


/*
            while(this.environmentData == null) {
                console.log('@@@WOODSMAN appConfig is null even after service call');
            }
*/
            if(this.constants == null) {
                console.log('@@@WOODSMAN appConfig is null even after service call');
            }
        };
        console.log('@@WOODSMAN: environmentData result = '+JSON.stringify(this.constants));
    }

    private setConstants(environmentData) {
        console.log('@@WOODSMAN calling environmentData='+JSON.stringify(environmentData));
        this.constants = new (environmentData);
    }

    get config() {
        //return this.appConfig;
        if(this.constants==null) {
            console.log('@@WOODSMAN Call to config found null appConfig.  Calling the load');
            this.loadAppConfig();
            if(this.constants==null) {
                console.log('@@WOODSMAN Second call to config still found null appConfig.');
            }
        }
        console.log('@@WOODSMAN environment.salesconnectURL' + this.constants["baseUrl"]);
        console.log('@@WOODSMAN environment.salesconnectURL' + this.constants["homepageURL"]);
        console.log('@@@WOODSMAN end getConstants ');
        return this.constants;
    }

}

Я вижу в браузере журнал этих двух строк в этом порядке (без операторов журнала между ними). '@@ WOODSMAN: ожидание информации об окружающей среде от вызова службы' '@@@ WOODSMAN appConfig имеет значение null даже после вызова службы'

Я попытался обернуть это в функцию asyn c и добавить инструкцию await, но он по-прежнему игнорировал это и не ждал завершения.

Поскольку для завершения службы требуется миллисекунды, я попытался добавить некоторое время l oop выше, чтобы дождаться, пока значение не будет установлено. Тем не менее, он стал навсегда l oop, так как обработчику службы не было позволено выполнить условие l oop.

*** Обновление

Я попытался добавить запрос вызова, который предлагает синхронную возможность. Поэтому я кодировал следующее:

            let ajaxObject = {
                type: "POST"
                ,headers: {
                     'Accept-Encoding' : 'application/json; charset=UTF-8'
                    ,'Content-Type' : 'application/json; charset=UTF-8'
                    ,'SC_TRACE_ID' : UUID.UUID()
                }
                ,url: "/proxy/report/getEnvironment"
                ,async : false
                ,data: "" 
                ,success: function(data) {
                    this.status="SUCCESS";
                    this.dataReturned = data;
                    console.log('@@WOODSMAN success reached');
                }
                ,error: function(jqXHR, textStatus, errorThrown) {
                    this.status="FAILURE";
                    this.jqXHR = jqXHR;
                    this.textStatus = textStatus;
                    this.errorThrown = errorThrown;
                    console.log('@@WOODSMAN failure reached');
                    console.log('Error on call to getEnvironment.  '+textStatus+' '+errorThrown);
                }
                ,status: "NOT_RUN"
                ,dataReturned : null
                ,jqXHR: {}
                ,textStatus: {}
                ,errorThrown: {} 
            };
            $.ajax(ajaxObject);
            console.log('@@@WOODSMAN after ajax service call' + JSON.stringify(ajaxObject));

Когда я запускаю это, я получаю «@@@ WOODSMAN после ajax вызова службы» со статусом «NOT_RUN»; Это означает, что в момент вызова он не выполнял ни функции успеха, ни ошибки. Обратите внимание, что запрос имеет асин c: false, установлен, поэтому у него нет оправдания асинхронному вызову.

Возможно ли программирование сокетов в Javascript? Становится очевидным, что синхронный вызов становится невероятно трудным.

1 Ответ

2 голосов
/ 26 марта 2020

Вы должны знать, что JS является асинхронным, означает любой код, который имеет дело с WEB API. Он не будет ждать его завершения, вместо этого он продолжит выполнение следующей строки кодов.

В совместно используемом вами фрагменте строки

let appConfig = http.post("/proxy/report/getEnvironment", "",httpOptions)
                .toPromise().then(data => { 
                this.setConstants(data);
            });

являются асинхронными. Следовательно, механизм JS не будет ждать его завершения и выполнит следующую строку кода. то есть:

if(this.constants == null) {
                console.log('@@@WOODSMAN appConfig is null even after service call');
            }

Поскольку вышеупомянутые строки выполняются до завершения вызова службы, значение this.constants в это время равно null. По этой причине вы можете видеть последний оператор в консоли.

Чтобы проверить, является ли this.constants null даже после вызова службы, вы можете изменить код, как показано ниже:

let appConfig = http.post("/proxy/report/getEnvironment", "",httpOptions)
                .toPromise().then(data => { 
                this.setConstants(data);
                if(this.constants == null) {
                console.log('@@@WOODSMAN appConfig is null even after service call');
            }
        });

** обновление. :

это способ, которым вы должны реализовать async-await. :

public  async loadAppConfig() {
        let http = this.injector.get(HttpClient);

            let appConfig = await http.post("url",{options})
                .toPromise().then(data => { 
                  .... next lines
            });

           console.log('this line will not execute until await is finished');

    } 

Вот демонстрация стекаблиц. : демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...