Это продолжение моего вопроса /10204235/google-translate-api-i-firebase-firestore-ubivayt-drug-druga
. Даг Стивенсон сказал, что мне нужно вернуть свои функции. Мы смотрели его видео Learn JavaScript Promises (Pt. 3) for sequential and parallel work in Cloud Functions
несколько сотен раз ...
Я работаю с двумя функциями. Во-первых, вызов Google Translate, теперь возвращает перевод. Вторая функция - это вызов Firestore set()
, чтобы записать перевод в базу данных. set()
работает, если я не делаю вызов Google Translate, но вместе они терпят крах. В частности, если я вызываю Firebase set()
, тогда выполняется функция Google Translate, мы видим Result1
и ничего более. Другими словами, вызов базы данных перестает кодировать толкание перевода в translationArray
.
Вот мой код:
exports.Google_EStranslateEN = functions.firestore.document('Users/{userID}/Spanish/Translation_Request_NOT').onUpdate((change, context) => {
if (change.after.data().word != undefined) {
const {Translate} = require('@google-cloud/translate');
// Your Google Cloud Platform project ID
const projectId = 'myProject-cd99d';
// Instantiates a client
const translate = new Translate({
projectId: projectId,
});
// The text to translate
const text = change.after.data().word;
console.log(text);
// The target language
const target = 'en';
let translationArray = []; // clear translation array
const finalPromise = translate.translate(text, target)
.then(function(results) {
console.log("Result1: " + results);
console.log(Array.isArray(results));
console.log(results[0]);
let translation = results[0];
console.log(translation);
return translation
})
.then(function(results) {
console.log("Translation: " + results);
translationArray.push(results);
return translationArray
})
.then(function(results) {
console.log("TranslationArray: " + translationArray);
console.log("Result2: " + results);
console.log("Text: " + text)
return admin.firestore().collection('Dictionaries').doc('Spanish').collection('Words').doc(text).collection('Translations').doc('English').set({
translationArray: results,
language: 'en',
longLanguage: 'English'
});
})
.then(function(results) {
console.log("Result3: " + results)
console.log("Write succeeded!");
})
.catch(function(error) {
console.error(error);
});
} // close if
return 0;
}); // close oxfordPronunciationUS
Вызов Firestore set()
ничего не возвращает и убивает вызов Google Translation. В частности, без вызова Firestore код выполняется полностью, регистрируя все. При вызове Firestore ни одна из функций не выполняется (Google Translate никогда не вызывается) и ничего не записывается после «text».
Я не понимаю, что делает const finalPromise
. Это похоже на неиспользованную константу.
Мы прочитали Почему API Firebase асинхронный? и попробовали этот код:
var promise = admin.firestore().collection('Dictionaries').doc('Spanish').collection('Words').doc(text).collection('Translations').doc('English').set({
translationArray: translationArray,
language: 'en',
longLanguage: 'English'
});
promise.then(...)
Это не помогло.
Я попытался перейти на IBM Watson Translate, и происходит то же самое. Без вызова базы данных функция перевода работает отлично. При вызове Firestore он получает перевод, запускает forEach
, а затем останавливается, когда я пытаюсь вставить слово в массив. translationsArray
не регистрируется и ничего не записывает в базу данных.
exports.IBM_EStranslateEN = functions.firestore.document('Users/{userID}/Spanish/Translation_Request_IBM').onUpdate((change, context) => {
if (change.after.data().word != undefined) {
let word = change.after.data().word;
let wordArray = [];
wordArray.push(word);
var LanguageTranslatorV3 = require('watson-developer-cloud/language-translator/v3');
var languageTranslator = new LanguageTranslatorV3({
version: '2018-05-01',
iam_apikey: 'swordfish',
url: 'https://gateway.watsonplatform.net/language-translator/api',
headers: {
'Content-Type': 'application/json'
}
});
var parameters = {
"text": wordArray,
"model_id": "es-en",
"source": "es",
"target": "en"
};
let translationsArray = [];
languageTranslator.translate(
parameters,
function (err, response) {
if (err) {
console.log('error:', err);
} else {
response.translations.forEach(function(translation) {
console.log(translation.translation);
translationsArray.push(translation.translation);
});
console.log(translationsArray);
admin.firestore().collection('Dictionaries').doc('Spanish').collection('Words').doc(word).collection('Translations').doc('English').set({
translationsArray: translationsArray,
language: 'en',
longLanguage: 'English'
})
.then(function() {
console.log("Translations written to database.");
})
.catch(function(error) {
console.error(error);
});
}
}
);
}
return 0;
});
Я также написал ту же облачную функцию, вызывая Оксфордский словарь английского языка для перевода. Это отлично работает, запись перевода в базу данных:
exports.Oxford_EStranslateEN = functions.firestore.document('Users/{userID}/Spanish/Translation_Request').onUpdate((change, context) => {
if (change.after.data().word != undefined) {
let word = change.after.data().word;
let options = {
uri: 'https://od-api.oxforddictionaries.com/api/v1/entries/es/' + change.after.data().word + '/translations%3Den', // translations=es
headers: {
"Accept": "application/json",
'app_id': 'groucho',
'app_key': 'swordfish'
},
json: true
};
let translationsArray=[];
return rp(options)
.then(function (wordObject) {
wordObject.results.forEach(function(result) {
result.lexicalEntries.forEach(function(lexicalEntry) {
lexicalEntry.entries.forEach(function(entry) {
entry.senses.forEach(function(sense) {
if (sense.translations) {
sense.translations.forEach(function(translation) {
translationsArray.push(translation.text);
});
} // close if
else {
if (sense.subsenses) {
sense.subsenses.forEach(function(subsense) {
if (subsense.translations) {
subsense.translations.forEach(function(translation) {
translationsArray.push(translation.text);
}); // close forEach
} // close if
else {
// console.log("No Translation");
} // close else
}); // close forEach
} // close if
} // close else
}); // close forEach
}); // close forEach
}); // close forEach
}); // close forEach
translationsArray = [...new Set(translationsArray)]; // removes duplicates
return admin.firestore().collection('Dictionaries').doc('Spanish').collection('Words').doc(word).collection('Translations').doc('English').set({
translationsArray: translationsArray,
source: 'OED',
dateAdded: Date.now(), // timestamp
longLanguage: 'English',
shortLanguage: 'en',
word: word
})
.then(function() {
// console.log("Document written.");
})
.catch(function(error) {
console.log("Error writing document: ", error);
})
})
.then(function(){
// console.log("Document written for Oxford_EStranslateEN.");
})
.catch(function (error) {
console.log("error: " + error);
});
} // close if
// return 0;
});
Единственное отличие состоит в том, что я вызываю OED через HTTP-запрос, используя rp
(запрос-обещание). Я звоню return rp(options)
. Это ясно возвращает обещание, и обещание возвращается явно. Кажется, проблема в том, что в версии Google я не возвращаю обещание при вызове Google Translate, а IBM Watson возвращает обратный вызов, а не обещание, и я его не возвращаю.