JSONP 回调和闭包/范围

JSONP Callbacks and Closures/Scope

本文关键字:范围 闭包 回调 JSONP      更新时间:2023-09-26

我正在使用Microsoft翻译 api(AJAX 版本)来自 http://www.microsofttranslator.com/dev/

我在闭包和回调方面遇到了一些问题,我希望这段代码能够证明这一点:

function translate(original){
    window.translateComplete = function(language) {
        if (language!="en"){
        alert(original +" "+language);
        }   
    }

    var windowsliveid = 'API_KEY_REMOVED';
    var el = document.createElement("script"); 
    el.src = 'http://api.microsofttranslator.com/V2/Ajax.svc/Detect'; 
    el.src += '?oncomplete=translateComplete'; 
    el.src += '&appId=' + windowsliveid; 
    el.src += '&text=' + escape (original); 
    document.getElementsByTagName('head')[0].appendChild (el);
}
translate("Au Revoir"); 
translate("Hola"); 

现在,我的回应是

Hola es
Hola fr

在回调有机会执行之前,original变量被覆盖。

我如何避免这种情况,以便它显示类似以下内容:

Hola es
Au revoir fr

我正在尝试在不使用 jQuery 和 when() 的情况下执行此操作

谢谢

好吧,你对每个响应使用相同的回调函数,因为window. translateComplete只能引用一个函数。因此,每次调用translate都会用一个新函数覆盖window.translateComplete,这是一个闭包。

您可以为每个调用创建一个具有不同名称的新回调。这就是jQuery正在做的事情。

最简单的形式是:

var i = 0; // some running variable
function translate(original){
    var cb_name = 'cb' + (i++); // create a new name
    window[cb_name]= function(language) {
        delete window[cb_name]; // remove function to not pollute the global scope
        if (language!="en"){
            alert(original +" "+language);
        }   
    }
    var windowsliveid = 'API_KEY_REMOVED';
    var el = document.createElement("script"); 
    el.src = 'http://api.microsofttranslator.com/V2/Ajax.svc/Detect'; 
    el.src += '?oncomplete=' + cb_name; // use the dynamic name instead
    el.src += '&appId=' + windowsliveid; 
    el.src += '&text=' + escape (original); 
    document.getElementsByTagName('head')[0].appendChild (el);
}
这是因为

您在调用"translate"时重新分配了全局"translateComplete"函数。 只能有一个函数绑定到"窗口"的单个属性,对吧?

("原始"变量没有被改变;只是第一个函数,"Au Revoir",被完全抛弃,在等待垃圾回收时漫无目的地漂浮。