Javascript 承诺:遍历所有对象键数组然后解析
Javascript Promises: Iterate over all object keys arrays and then resolve
我有这个 JS 对象:
let setOfWords = {
"nouns": [
"work",
"construction",
"industry"
],
"verbs": [
"work"
],
}
我正在使用调用 REST 资源的 google 翻译 API,所以我需要等待每个翻译的响应,然后解析相同的对象结构,但使用翻译的词.
function translateByCategory(){
let translatedObj = {};
return new Promise(function(resolve, reject){
Object.keys(obj).forEach(function(category){
if (translatedObj[category] == undefined) {
translatedObj[category] = [];
}
setOfWords.forEach(function(word){
google.translate(word, 'es', 'en').then(function(translation){
translatedObj[category].push(translation.translatedText);
});
});
// return the translatedObj until all of the categories are translated
resolve(translatedObj);
});
});
}
您可以使用 Promise.all()
等待所有承诺履行(或第一次拒绝):
var translateRequests = [];
Object.keys(setOfWords).forEach(function(category){
setOfWords[category].forEach(function(word){
translateRequests.push(google.translate(word, 'es', 'en'));
});
});
});
Promise.all(translateRequests).then(function(translateResults){
//do something with all the results
});
查看文档:Promise.all()
个人承诺需要与 Promise.all()
聚合,从根本上说,这就是所缺少的。
但是您可以通过减少对 Google 服务的调用次数来做得更好。
Google translate API 通过传递一组单词而不是每次调用一个单词,允许在一次点击中翻译多个文本字符串,为您提供性能优势,但可能不是价格优势- google 目前对其翻译服务收费 "per character",而不是 "per call"。
我找不到 google.translate()
的任何文档,但是,根据一些假设,您可以编写:
function translateByCategory(obj, sourceCode, targetCode) {
let translatedObj = {};
var promises = Object.keys(obj).map(function(key) {
return google.translate(obj[key], sourceCode, targetCode).then(function(translations) {
translatedObj[key] = translations.map(function(t) {
return t.translatedText || '-';
});
}, function(error) {
translatedObj[key] = [];
});
});
return Promise.all(promises).then(function() {
return translatedObj;
});
}
如果这不起作用,那么 this documentation 会解释如何直接调用 google 的 RESTful 翻译服务。
你应该会写:
function translateTexts(baseParams, arrayOfStrings) {
let queryString = baseParams.concat(arrayOfStrings.map(function(str) {
return 'q=' + encodeURIComponent(str);
})).join('&');
return http.ajax({ // some arbitrary HTTP lib that GETs by default.
url: 'https://translation.googleapis.com/language/translate/v2?' + queryString,
}).then(function(response) {
return response.data.translations.map(function(t) {
return t.translatedText || '-';
});
}, function(error) {
translatedObj[key] = []; // on error, default to empty array
});
}
function translateByCategory(obj, sourceCode, targetCode) {
let baseParams = [
'key=' + MY_API_KEY, // from some outer scope
'source=' + sourceCode, // eg 'en'
'target=' + targetCode // eg 'es'
];
let translatedObj = {};
let promises = Object.keys(obj).map(function(key) {
return translateTexts(baseParams, obj[key]).then(function(translations) {
translatedObj[key] = translations;
}, function(error) {
translatedObj[key] = []; // on error, default to empty array
});
});
return Promise.all(promises).then(function() {
return translatedObj;
});
}
无论哪种情况,调用如下:
let setOfWords = {
"nouns": [
"work",
"construction",
"industry"
],
"verbs": [
"work"
],
};
translateByCategory(setOfWords, 'en', 'es').then(function(setOfTranslatedWords) {
console.log(setOfTranslatedWords);
});
可以修改 @hackerrdave 建议的方法,使其更兼容 JavaScript 的异步等待功能,请按以下方式操作:
function translateByCategory(){
return new Promise(function(resolve, reject){
var translateRequests = [];
Object.keys(setOfWords).forEach(function(category){
setOfWords[category].forEach(function(word){
translateRequests.push(google.translate(word, 'es', 'en'));
});
});
Promise.all(translateRequests).resolve(resolve(translateRequests));
});
}
现在您可以执行以下操作:
let translatedObj = await translateByCategory();
你会在"translatedObj"得到你想要的。
我有这个 JS 对象:
let setOfWords = {
"nouns": [
"work",
"construction",
"industry"
],
"verbs": [
"work"
],
}
我正在使用调用 REST 资源的 google 翻译 API,所以我需要等待每个翻译的响应,然后解析相同的对象结构,但使用翻译的词.
function translateByCategory(){
let translatedObj = {};
return new Promise(function(resolve, reject){
Object.keys(obj).forEach(function(category){
if (translatedObj[category] == undefined) {
translatedObj[category] = [];
}
setOfWords.forEach(function(word){
google.translate(word, 'es', 'en').then(function(translation){
translatedObj[category].push(translation.translatedText);
});
});
// return the translatedObj until all of the categories are translated
resolve(translatedObj);
});
});
}
您可以使用 Promise.all()
等待所有承诺履行(或第一次拒绝):
var translateRequests = [];
Object.keys(setOfWords).forEach(function(category){
setOfWords[category].forEach(function(word){
translateRequests.push(google.translate(word, 'es', 'en'));
});
});
});
Promise.all(translateRequests).then(function(translateResults){
//do something with all the results
});
查看文档:Promise.all()
个人承诺需要与 Promise.all()
聚合,从根本上说,这就是所缺少的。
但是您可以通过减少对 Google 服务的调用次数来做得更好。
Google translate API 通过传递一组单词而不是每次调用一个单词,允许在一次点击中翻译多个文本字符串,为您提供性能优势,但可能不是价格优势- google 目前对其翻译服务收费 "per character",而不是 "per call"。
我找不到 google.translate()
的任何文档,但是,根据一些假设,您可以编写:
function translateByCategory(obj, sourceCode, targetCode) {
let translatedObj = {};
var promises = Object.keys(obj).map(function(key) {
return google.translate(obj[key], sourceCode, targetCode).then(function(translations) {
translatedObj[key] = translations.map(function(t) {
return t.translatedText || '-';
});
}, function(error) {
translatedObj[key] = [];
});
});
return Promise.all(promises).then(function() {
return translatedObj;
});
}
如果这不起作用,那么 this documentation 会解释如何直接调用 google 的 RESTful 翻译服务。
你应该会写:
function translateTexts(baseParams, arrayOfStrings) {
let queryString = baseParams.concat(arrayOfStrings.map(function(str) {
return 'q=' + encodeURIComponent(str);
})).join('&');
return http.ajax({ // some arbitrary HTTP lib that GETs by default.
url: 'https://translation.googleapis.com/language/translate/v2?' + queryString,
}).then(function(response) {
return response.data.translations.map(function(t) {
return t.translatedText || '-';
});
}, function(error) {
translatedObj[key] = []; // on error, default to empty array
});
}
function translateByCategory(obj, sourceCode, targetCode) {
let baseParams = [
'key=' + MY_API_KEY, // from some outer scope
'source=' + sourceCode, // eg 'en'
'target=' + targetCode // eg 'es'
];
let translatedObj = {};
let promises = Object.keys(obj).map(function(key) {
return translateTexts(baseParams, obj[key]).then(function(translations) {
translatedObj[key] = translations;
}, function(error) {
translatedObj[key] = []; // on error, default to empty array
});
});
return Promise.all(promises).then(function() {
return translatedObj;
});
}
无论哪种情况,调用如下:
let setOfWords = {
"nouns": [
"work",
"construction",
"industry"
],
"verbs": [
"work"
],
};
translateByCategory(setOfWords, 'en', 'es').then(function(setOfTranslatedWords) {
console.log(setOfTranslatedWords);
});
可以修改 @hackerrdave 建议的方法,使其更兼容 JavaScript 的异步等待功能,请按以下方式操作:
function translateByCategory(){
return new Promise(function(resolve, reject){
var translateRequests = [];
Object.keys(setOfWords).forEach(function(category){
setOfWords[category].forEach(function(word){
translateRequests.push(google.translate(word, 'es', 'en'));
});
});
Promise.all(translateRequests).resolve(resolve(translateRequests));
});
}
现在您可以执行以下操作:
let translatedObj = await translateByCategory();
你会在"translatedObj"得到你想要的。