/ / Obietnica Ionic dla iOS nigdy nie rozwiązuje - kątowa, ionic-framework, obietnica, ionic3, zonejs

Obietnica ionic iOS nigdy nie rozwiązuje się - angular, ionic-framework, promise, ionic3, zonejs

Wdrażam logowanie Google w mojej aplikacji Ionic 3 za pomocą Firbase. Z powodzeniem mogłem korzystać z natywna wtyczka Google Plus Cordova, a następnie zaloguj się przy użyciu poświadczeń do Firebase przy użyciu Angular Fire 2. Oto mój kod:

public loginWithGoogle(): Promise<any> {

return new Promise((resolve, reject) => {

let loginPromise: Promise<any>;

if (this.isMobile()) {
loginPromise = new Promise((resolve, reject) => {
this.googleplus.login({
"webClientId": "--------.apps.googleusercontent.com",
"offline": true
})
.then(res => {
this.afAUth.auth.signInWithCredential(firebase.auth.GoogleAuthProvider.credential(res.idToken))
.then(firebaseRes => {
resolve(firebaseRes);
})
.catch(err => {
reject(err);
});
})
.catch(err => {
reject(err);
});
});
} else {
loginPromise = this.afAUth.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider()) as Promise<any>;
}

loginPromise
.then(res => {
console.log("login promise done: " + JSON.stringify(res));

const user: User = {
uid: res.user.uid,
email: res.user.email,
displayName: res.user.displayName
};

resolve(user);
});
});
}

I wezwanie do tego na mojej stronie logowania:

this.auth.loginWithGoogle()
.then(res => {
console.log("success login !!!!!");
})
.catch(err => {
console.log("error login !!!!!");
});

Jednak po wdrożeniu do systemu iOS za pomocą Xcode widzę dane wyjściowe konsoli:

2017-06-11 11:32:01.384130 MyApp[2634:842028] login promise done: {"uid":"...","displayName":"...","photoURL":"..."...}

Obietnica nigdy nie rozwiązuje się! Próbowałem używać ZoneJS ręcznie, ale bezskutecznie:

private zone;

public loginWithGoogle(): Promise<any> {

this.zone = new NgZone({});

...

this.zone.run(() => {
resolve(user);
});
});
});
}

Ale wynik jest taki sam. Aby uzyskać informacje, logowanie działa poprawnie w przeglądarce.

Odpowiedzi:

1 dla odpowiedzi № 1

Problem pochodzi z dostępu res.user, który istnieje tylko podczas logowania za pomocą wyskakującego okienka. Obiekt zwrócony podczas logowania przy użyciu poświadczeń zawiera uid, email i inne właściwości użytkownika w jego katalogu głównym. Musisz utworzyć użytkownika w różny sposób, niezależnie od tego, czy jesteś w środowisku mobilnym czy altanowym. Na telefonie komórkowym dostęp res.user.uid i dostęp do przeglądarki res.uid.

IMHO jest to wprowadzająca w błąd specyfikacja interfejsu po stronie Angular Fire.

Ponadto kod jest trudny do odczytania. Łańcuchy obietnic nie są dobrą praktyką. Jeśli to możliwe, używaj Observables bezpośrednio, a gdy nie jest to możliwe, zamień obietnice na Observables przy użyciu RxJS fromPromise operator. Następnie możesz płasko mapować wyniki, aby łączyć asynchroniczne wywołania i uzyskać czysty kod. Jedną z zalet Observables jest to, że wywołanie zwrotne błędu subscribe funkcja wyłapie każdy błąd, który wystąpił podczas łańcucha, a przy obietnicach musisz złapać i odrzucić ręcznie.

Przy odrobinie refaktoryzacji otrzymasz następujące (które działa):

private signInWithGooglePlus(): Observable<any> {
return Observable.fromPromise(
...
);
}

private signInFirebaseWithCredentials(idToken: string): Observable<User> {
return Observable.fromPromise(
...
).map(credentials => ({
uid: credentials.uid,
...
}));
}

private signInWithGooglePopup(): Observable<User> {
return Observable.fromPromise(
...
).map(firebaseRes => ({
uid: firebaseRes.user.uid,
...
}));
}

public loginWithGoogle(): Observable<any> {

let loginPromise: Observable<User>;

if (this.isMobile()) {
loginPromise = this.signInWithGooglePlus().flatMap(res => this.signInFirebaseWithCredentials(res.idToken));
} else {
loginPromise = this.signInWithGooglePopup();
}

let user: User;

return loginPromise
.flatMap(userTmp => {
user = userTmp;
return this.getJWTToken(userTmp.uid);
})
.map(token => {
this.storeData(token, user);
return user;
});
}