AFAIK невозможно напрямую связать два процесса, подразумеваемых в вашем приложении:
- С одной стороны, у вас реализован поток входа в Google в ваш пользовательский интерфейс (даже если во внутреннем интерфейсе есть вызов службы аутентификации) и;
- С другой стороны, у вас есть облачная функция, которая выполняется в back-end .
Проблема, с которой вы столкнулись, связана с тем фактом, что , как только поток входа в Google будет успешным, ваш пользователь подписан в ваше приложение и пытается прочитать документ , который будет создан с помощью облачной функции.
В некоторых случаях (например, из-за холодного запуска облачной функции) этот документ еще не создан при входе пользователя, что приводит к ошибке.
Одним из возможных решений будет установите прослушиватель Firestore на своем внешнем интерфейсе, чтобы дождаться создания этого документа, следующим образом. Обратите внимание, что следующий код учитывает только документ Firestore, созданный функцией addFirst()
, так как вы не предоставляете никаких сведений о втором документе, который будет создан с помощью addSecond()
.
firebase.auth().signInWithPopup(provider)
.then(function(result) {
var token = result.credential.accessToken;
var user = result.user;
//Here we know the userId then we can set a listener to the doc languages/${user.uid}
firebase.firestore().collection("languages").doc(user.uid)
.onSnapshot(function(doc) {
if(doc.exists) {
console.log("Current data: ", doc.data());
//Do whatever you want with the user doc
} else {
console.log("Language document not yet created by the Cloud Function");
}
});
}).catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
var email = error.email;
var credential = error.credential;
// ...
});
Как сказано выше, в приведенном выше коде мы учитываем только первый документ Firestore, созданный функцией addFirst()
. Но вам, вероятно, нужно дождаться создания двух документов, прежде чем читать их из внешнего интерфейса.
Итак, вы можете изменить свой CF следующим образом:
export const createCollection = functions.auth.user().onCreate(async user => {
try {
await addFirst();
await addSecond();
return null;
async function addFirst() {
const userRef = admin.firestore().doc(`languages/${user.uid}`);
await userRef.set(
{
language: null
},
{ merge: true }
);
}
async function addSecond() {
// ...
}
} catch (error) {
console.log(error);
return null;
}
});
Обратите внимание, что вы не нужно использовать Promise.all()
: следующие две строки уже выполняют две записи документа в Firestore. И, поскольку вы используете async/await
, второй документ пишется только после того, как написан первый.
const addLanguages = await addFirst();
const addSecondCollection = await addSecond();
Так что вам просто нужно установить слушателя на путь второго документа, и все готово !
Наконец, обратите внимание, что выполнение
throw new functions.https.HttpsError('unknown', error);
в вашем блоке catch
- это способ обработки ошибок для функции Callable Cloud. Здесь вы пишете фоновую функцию Cloud, и вы можете просто использовать return null;