wake-up-neo.com

Verschluckte Nachricht: Fehler: Nicht erfasst (im Versprechen): [Objekt undefiniert]

Meine Login-Komponente wird kurz angezeigt, bevor sie durch eine Fehlermeldung zu einem undefinierten Objekt in einem Versprechen entfernt wird.

Hier ist die Definition des Versprechens:

  static init(): Promise<any> {
    KeycloakClientService.auth.loggedIn = false;
    return new Promise((resolve, reject) => {
      const keycloakConfig = {
      url: environment.KEYCLOAK_URL,
      realm: environment.KEYCLOAK_REALM,
      clientId: environment.KEYCLOAK_CLIENTID,
      'ssl-required': 'external',
      'public-client': true
      };
      const keycloakAuth: any = new Keycloak(keycloakConfig);

      keycloakAuth.init({onLoad: 'check-sso'})
        .success(() => {
          KeycloakClientService.auth.loggedIn = true;
          KeycloakClientService.auth.authz = keycloakAuth;
          KeycloakClientService.auth.logoutUrl = environment.KEYCLOAK_URL
          + '/realms/' + environment.KEYCLOAK_REALM + '/protocol/openid-connect/logout?redirect_uri='
          + document.baseURI;
          console.log('=======>> The keycloak client has been initiated successfully');
          resolve('Succeeded in initiating the keycloak client');
        })
        .error(() => {
          reject('Failed to initiate the keycloak client');
        });
    });
  }

Es wird aufgerufen von:

KeycloakClientService.init()
  .then(
    () => {
      console.log('The keycloak client has been initialized');
    }
  )
  .catch(
    (error) => {
      console.log(error);
      window.location.reload();
    }
  );

Die Konsole zeigt beide Meldungen:

The keycloak client has been initiated successfully
The keycloak client has been initialized

Ich verwende Angular 6.0.4 und habe versucht, diesem zu folgen blog

Wie kann dieser Fehler behoben werden, damit mein Anmeldeformular angezeigt wird?

UPDATE: Ich habe versucht, ein beobachtbares statt eines Versprechens zu verwenden, aber das Thema blieb gleich:

  public init(): Observable<any> {
    KeycloakClientService.auth.loggedIn = false;
    return new Observable((observer) => {
      const keycloakConfig = {
        'url': environment.KEYCLOAK_URL,
        'realm': environment.KEYCLOAK_REALM,
        'clientId': environment.KEYCLOAK_CLIENTID,
        'ssl-required': 'external',
        'public-client': true
      };
      const keycloakAuth: any = new Keycloak(keycloakConfig);

      keycloakAuth.init({ 'onLoad': 'check-sso' })
        .success(() => {
          KeycloakClientService.auth.loggedIn = true;
          KeycloakClientService.auth.authz = keycloakAuth;
          KeycloakClientService.auth.logoutUrl = environment.KEYCLOAK_URL
            + '/realms/' + environment.KEYCLOAK_REALM + '/protocol/openid-connect/logout?redirect_uri='
            + document.baseURI;
          console.log('The keycloak auth has been initialized');
          observer.next('Succeeded in initiating the keycloak client');
          observer.complete();
        })
        .error(() => {
          console.log('The keycloak client could not be initiated');
          observer.error('Failed to initiate the keycloak client');
        });
    });
  }

Der gesamte Quellcode ist auf GitHub verfügbar.

UPDATE: Nach einer Antwort unten habe ich auch versucht, ein then()- und ein catch()-Schlüsselwort zu verwenden, der Fehler blieb jedoch derselbe:

keycloakAuth.init({ 'onLoad': 'check-sso' })
        .then(() => {
          KeycloakClientService.auth.loggedIn = true;
          KeycloakClientService.auth.authz = keycloakAuth;
          KeycloakClientService.auth.logoutUrl = environment.KEYCLOAK_URL
            + '/realms/' + environment.KEYCLOAK_REALM + '/protocol/openid-connect/logout?redirect_uri='
            + document.baseURI;
          console.log('The keycloak auth has been initialized');
          observer.next('Succeeded in initiating the keycloak client');
          observer.complete();
        })
        .catch(() => {
          console.log('The keycloak client could not be initiated');
          observer.error('Failed to initiate the keycloak client');
        });
8
Stephane

Dies ist eine wilde Vermutung, aber vielleicht ist es ein Konflikt mit den Zonen von Angular. Da dies eine Sicherheitsbibliothek ist, mag es nicht so sein, dass Angular Kernfunktionen durch Proxys ersetzt hat. Beispielsweise ändert NgZonewindow.setTimeout und die HTTP-Methoden.

Sie können also versuchen, diesen Code außerhalb von Zonen auszuführen. Das einzige Problem hier ist, dass Sie eine static - Funktion verwenden und dies zu einem injizierbaren Dienst machen müssen, damit Sie auf NgZone zugreifen können.

@Injectable()
export class KeycloakClientService {
    public constructor(private zone: NgZone) {
    }

    public init(): Promise<any> {
        KeycloakClientService.auth.loggedIn = false;
        return new Promise((resolve, reject) => {
            this.zone.runOutsideAngular(() => {
                const keycloakConfig = {
                     url: environment.KEYCLOAK_URL,
                     realm: environment.KEYCLOAK_REALM,
                     clientId: environment.KEYCLOAK_CLIENTID,
                     'ssl-required': 'external',
                     'public-client': true
                };

                const keycloakAuth: any = new Keycloak(keycloakConfig);

                keycloakAuth.init({onLoad: 'check-sso'})
                    .success(() => {
                        KeycloakClientService.auth.loggedIn = true;
                        KeycloakClientService.auth.authz = keycloakAuth;
                        KeycloakClientService.auth.logoutUrl = environment.KEYCLOAK_URL
                            + '/realms/' + environment.KEYCLOAK_REALM + '/protocol/openid-connect/logout?redirect_uri='
                            + document.baseURI;
                        console.log('=======>> The keycloak client has been initiated successfully');
                        resolve('Succeeded in initiating the keycloak client');
                    })
                    .error(() => {
                        reject('Failed to initiate the keycloak client');
                    });
            });
        }
    }
}

Die Änderung hier ist, zone.runOutsideAngular zu verwenden

3
cgTag

Wenn Sie den success-Block entfernen, wo führen Sie Ihre Logik in success aus?

Ich habe etwas von ihrem Quellcode gelesen, ich denke, dass success das Problem verursacht:

Innerhalb von keycloak.js gibt es eine Funktion createNativePromise():

function createNativePromise() {
var p = {
    setSuccess: function(result) {
        p.success = true;
        p.resolve(result);
    },

    setError: function(result) {
        p.success = false;
        p.reject(result);
    }
};
p.promise = new Promise(function(resolve, reject) {
    p.resolve = resolve;
    p.reject = reject;
});
p.promise.success = function(callback) {
    p.promise.then(callback);
    return p.promise;
}
p.promise.error = function(callback) {
    p.promise.catch(callback);
    return p.promise;
}
return p;
}

Und es wird auf diese Weise verwendet (vereinfachter Code):

function refreshToken() {
    var promise = createNativePromise();
    ...
    if (refreshTokenFailed) {
        promise.setError(true);
    }
    ...

    return promise.promise;
}

Das Problem ist, promise.setError() ruft promise.reject(result) auf, also wird das Versprechen abgelehnt, es erwartet eine catch.

Aber innerhalb von promise.success gibt es eine promise.promise.then(callback);, und niemand hält dieses Versprechen.

Deshalb bekommst du die Uncaught (in promise): [object Undefined], und in meinem Fall bekomme ich immer Uncaught (in promise): true.

Lösung:

Beachten Sie, dass promise.promise eine echte Promise ist, sodass wir then und catch anstelle von success und error verwenden können.

Der Nachteil ist, dass der TypeScript-Typ falsch ist.

0
penghui