Ionic+Cordova移动端取消登录弹窗出现未捕获Promise异常求助
Hey there! I’ve run into this exact issue before with Cordova-powered Ionic apps—social login works perfectly when users complete the flow, but cancelling the dialog throws an uncaught promise error, even though Firebase’s web SDK handles it smoothly with a clear "User cancelled..." message. Let’s break down why this happens and how to fix it.
Why This Happens
The core difference lies in how Cordova’s social login plugins (like cordova-plugin-facebook4 or cordova-plugin-googleplus) handle cancellations compared to Firebase’s web SDK. On web, Firebase wraps cancellations as a handled promise rejection with a user-friendly message. But Cordova plugins? Their native-to-JS bridge often throws an uncaught error directly because it doesn’t map cancellations to a "clean" rejection like the web SDK does.
Step-by-Step Fixes
1. Explicitly Catch Promise Rejections Everywhere
The simplest fix is to ensure every login call has a .catch() block (or uses try/catch with async/await) to handle both cancellations and real errors. Don’t rely on Firebase’s web-style automatic handling here—Cordova needs explicit care.
Example for Facebook Login:
async function facebookLogin() { try { const loginResult = await FacebookLogin.login(['public_profile', 'email']); // Pass credentials to Firebase for authentication const credential = firebase.auth.FacebookAuthProvider.credential(loginResult.authResponse.accessToken); await firebase.auth().signInWithCredential(credential); // Success logic (e.g., navigate to home screen) } catch (error) { // Check if this is a user-initiated cancellation if (error.errorCode === '4201' || error.message.includes('cancelled')) { // 4201 is the standard Facebook Cordova plugin cancellation code console.log('User cancelled Facebook login'); // Show friendly feedback to the user const toast = await toastController.create({ message: 'You cancelled the login process', duration: 2500, position: 'bottom' }); await toast.present(); } else { // Handle actual errors (network issues, invalid permissions, etc.) console.error('Facebook login failed:', error); const errorToast = await toastController.create({ message: 'Login failed. Please try again.', duration: 3000, position: 'bottom', color: 'danger' }); await errorToast.present(); } } }
Example for Google Login:
Google’s Cordova plugin uses a different cancellation code (12501), so adjust your catch block accordingly:
async function googleLogin() { try { const googleUser = await GooglePlus.login({ scopes: 'email profile', webClientId: 'YOUR_WEB_CLIENT_ID_FROM_FIREBASE' }); const credential = firebase.auth.GoogleAuthProvider.credential(googleUser.idToken); await firebase.auth().signInWithCredential(credential); // Success logic } catch (error) { if (error.code === '12501' || error.message.includes('cancelled')) { console.log('User cancelled Google login'); // Show user feedback const toast = await toastController.create({ message: 'Login cancelled', duration: 2500, position: 'bottom' }); await toast.present(); } else { console.error('Google login failed:', error); // Handle real errors } } }
2. Use Plugin-Specific Error Codes
Each Cordova social plugin has its own error code for cancellations—these are more reliable than matching error messages (which can vary by version or platform):
- Facebook (
cordova-plugin-facebook4):4201= User cancelled login - Google (
cordova-plugin-googleplus):12501= User cancelled login
3. Add a Global Safety Net (Optional)
If you’re worried about missing a catch block somewhere, add a global listener for unhandled promise rejections to suppress cancellation errors without hiding real issues:
// Add this in your app's initialization (e.g., app.component.ts) window.addEventListener('unhandledrejection', (event) => { const rejectionReason = event.reason; // Check if this is a known cancellation error const isCancellation = rejectionReason?.errorCode === '4201' || rejectionReason?.code === '12501' || rejectionReason?.message?.toLowerCase().includes('cancelled'); if (isCancellation) { console.log('Handled uncaught cancellation error'); event.preventDefault(); // Stop the error from showing in the console } else { // Log real unhandled errors for debugging console.warn('Unhandled promise rejection:', rejectionReason); } });
Final Notes
Always keep your Cordova plugins, Ionic, and Firebase packages updated—sometimes these cancellation handling quirks get fixed in newer versions. Also, avoid mixing web Firebase login methods with Cordova plugins; stick to the plugin’s login flow first, then pass the credential to Firebase for authentication.
内容的提问来源于stack exchange,提问作者Dani

