/ / La promesse iOS ionique ne se résout jamais - angulaire, ionic-framework, promesse, ionic3, zonejs

La promesse ionique iOS ne résout jamais - angulaire, ionic-framework, promesse, ionic3, zonejs

J'implémente la connexion Google dans mon application Ionic 3 avec Firbase. J'ai réussi à utiliser le plugin natif Google Plus Cordova, puis connectez-vous avec des informations d'identification à Firebase en utilisant Feu angulaire 2. Voici mon code:

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);
});
});
}

Et l'appel à cela dans ma page de connexion:

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

Cependant, lorsque je déploie sur iOS avec Xcode, je peux voir la sortie de la console:

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

La promesse ne se résout jamais! J'ai essayé d'utiliser ZoneJS manuellement mais sans succès:

private zone;

public loginWithGoogle(): Promise<any> {

this.zone = new NgZone({});

...

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

Mais le résultat est le même. Pour plus d'informations, la connexion fonctionne correctement dans le navigateur.

Réponses:

1 pour la réponse № 1

Le problème vient de l'accès res.user, qui n'existe que lors de la connexion avec popup. L'objet renvoyé lors de la connexion avec les informations d'identification contient uid, email et d'autres propriétés utilisateur à sa racine. Vous devez créer l'utilisateur différemment, que vous soyez dans des environnements mobiles ou en tonnelle. Sur mobile, accès res.user.uid et sur l'accès au navigateur res.uid.

À mon humble avis, il s'agit d'une spécification d'interface trompeuse du côté de Angular Fire.

De plus, le code est difficile à lire. Les chaînes de promesses ne sont pas une bonne pratique. Lorsque cela est possible, utilisez directement Observables et, lorsque cela n'est pas possible, convertissez les promesses en Observables à l'aide de RxJS fromPromise opérateur. Vous pouvez ensuite FlatMap résultats pour enchaîner les appels asynchrones et obtenir un code propre. Un des avantages d'Observables est que le rappel d'erreur du subscribe La fonction interceptera toute erreur survenue pendant la chaîne, tandis qu'avec les promesses, vous devrez intercepter et rejeter manuellement.

Avec un peu de refactoring, vous obtenez ce qui suit (qui fonctionne):

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;
});
}