2016-11-22 49 views
1

我有这个JS对象:的Javascript承诺:遍历所有对象键的阵列,然后解决

let setOfWords = { 
    "nouns": [ 
     "work", 
     "construction", 
     "industry" 
    ], 
    "verbs": [ 
     "work" 
    ], 
} 

我使用谷歌翻译API,它调用REST资源,所以我需要等待响应的每个翻译,然后解析相同的对象结构,但与翻译的单词。

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

创建一个promise数组并使用'Promise.all'(两次,即每个循环)。不要使用新的Promise。 – Bergi

+0

@Bergi可以请你发表一个代码示例吗?我仍然无法理解'Promise.all()' – Gus

+0

顺便说一句,你确定要'推'字'而不是'翻译'吗? – Bergi

回答

3

您可以使用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 
}); 

见文档浏览:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

+1

更好地使用'map'而不是'forEach'来构造数组。虽然我们严重遗漏'concatMap'显然 – Bergi

+0

如果你有迭代的嵌套对象,你会如何干净地做到这一点? – qxz

+0

感谢你的这一点,它进行了一些修改,但现在我明白了'Promise.all()',@Bergi我仍然返回了一个Promise,但是在孩子承诺完成之后。 – Gus

0

个人的承诺需要与Promise.all()进行汇总,并从根本上,这是少了什么东西。

但是,您可以通过减少对Google服务的呼叫数量来做得更好。

谷歌翻译API允许通过传递一组单词而不是一个单词来翻译多个文本字符串,从而为您提供性能优势,虽然可能没有价格优势 - 谷歌目前对其翻译服务收费“每个字符“,而不是”每个电话“。

我找不到任何文档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解释如何调用谷歌的REST翻译直接服务。

你应该能够编写:

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

通过@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)); 
    }); 
} 

因此,现在y你可以做类似的事情:

let translatedObj = await translateByCategory(); 

而你会在“翻译对象”中得到你想要的。

+0

谢谢。我一直在阅读'async'和'await'。它不是应该取代承诺,它与'异步'一起工作?尽管如此,我还是不太明白。 – Gus