使用api调用在循环中实现promise

Implementing a promise within a loop with an api call

本文关键字:实现 promise 循环 api 调用 使用      更新时间:2023-09-26

我正在使用谷歌翻译api。

function translate() {
    var languages = [array of languages codes];
    for (var i = 1; i < languages.length; i++) {
        alert("working");
        GoogleTranslate(text, languages[i - 1], languages[i]);
        alert(text);
    }
}
function GoogleTranslate(text, fron, to) {
    var newScript = document.createElement('script');
    var sourceText = escape(text);
    newScript.type = 'text/javascript';
    var source = 'https://www.googleapis.com/language/translate/v2?key=APIKEY&source=' + from + '&target=' + to + '&callback=google_translation&q=' + sourceText;
    newScript.src = source;
    alert("sent");
    // send the request off to google by appending 
    $('head')[0].appendChild(newScript);
}
// callback
function google_translation(google_response) {
    text.val(google_response.data.translations[0].translatedText);
    alert("translated")
}

我想知道我的代码是以我想要的方式工作的,就是让警报按顺序出现:"工作"、"发送"、"翻译"、"文本"并重复。

相反,我得到的是"正在工作"、"已发送"、"文本"、"正在工作中"、"发送"和"文本"。。。"已翻译"。。这意味着整个googleapi调用在循环再次运行之前没有完成回调。

我读过并听说我可能想实现一个承诺,但我不确定如何实现,如果我以某种方式实现了,如何让它在一个循环中运行。有人能给我指一个好网站吗。我想用一个同步函数和一个异步函数运行promise,然后让循环继续,但大多数站点都专注于背靠背的异步调用。或者,如果可能的话,用另一种方法确保在循环继续之前完成整个api调用。非常感谢您的帮助!

编辑:我用ajax 调用api

function GoogleTranslate (text, from, to, where) {
var g_object = new Object;
g_object.key = "APIKEY";
g_object.source = from;
g_object.target = to;
g_object.q = text;
alert("1");
$.ajax({
  //async: false,
  type: "POST",
  url: "https://www.googleapis.com/language/translate/v2",
  data: g_object,
  dataType: 'jsonp',
  success: function (response) {
      alert("2");
      where.val(response.data.translations[0].translatedText);  
      alert("3");
  },
  error: function (response) {
    alert('Error:' + response.error.message);
  }
});
}

翻译后的文本应该放在哪里

我假设语言数组类似

['English', 'French', 'German', 'Klingon']

如果你想从英语->法语->德语->克林贡语翻译,代码似乎表明这就是你想要的目标

使用承诺是一个不错的解决方案

在下面的代码中,我使用var translate而不是function translate是有原因的,所以函数对象是完全自包含的

此外,translate必须是全局的,jsonp回调才能工作——但您可能知道

var translate = function translate(fromtext) {
    var iterate; // this will contain a function to call to jump to the next translation
    var languages = ['English', 'French', 'German', 'Klingon'];
    // this function hasn't changed from your example, except the callback is set to the function within this function
    function GoogleTranslate (text, from, to) {
        var newScript = document.createElement('script');
        var sourceText = escape(text);
        newScript.type = 'text/javascript';
        var source = 'https://www.googleapis.com/language/translate/v2?key=APIKEY&source=' + from + '&target=' + to + '&callback=translate.google&q=' + sourceText;
        // notice the callback is translate.google, exactly as defined below. ---------------------------------------------------^^^^^^^^^^^^^^^^
        newScript.src = source;
        console.log("sent");
        // send the request off to google by appending 
        document.head.appendChild(newScript); // use document.head i modern browsers
    }
    // this function hasn't changed, except the call to iterate at the end, and I removed the text.val() call as it made no sense to display the intermediate values of the translation
    translate.google = function (google_response) {
        console.log("translated");
        // when a translation has completed, go do the next one, resolving the promise with the result of this one
        iterate(google_response.data.translations[0].translatedText);
    }
    // slice(1) to work from 1 to end of array
    function reducer(promise, tolanguage, index) {
        //chain the translation to the result of the previous promise
        return promise.then(function(newtext) { // newtext is the result of the previous translation
            return new Promise(function(resolve, reject) { // return a new promise
                iterate = resolve; // iterate is called to resolve this promise
                console.log('working');
                // access the previous language through languages array
                // as we have copied the languages from index 1, use the same index in languages to get the from language
                GoogleTranslate(newtext, languages[index], tolanguage);
                console.log(newtext);
            });
        });
    }
    var destinationLanguages = languages.slice(1);
    var result = destinationLanguages.reduce(reducer, Promise.resolve(fromtext)); // prime the loop with the incoming word
    return result;
};

使用

translate('hello').then(function(result) {
    console.log(result); //
    // this is where you probably want to do the following
    text.val(result);
});

阵列缩减文档

如果您可以将CORS-json与www.googleapis.com/language/translate一起使用,那么代码会简单得多,也不会那么黑客化