Как я могу отправить функцию обратного вызова из глобального пространства имен в именованное пространство (проблема SCOPE) - PullRequest
1 голос
/ 26 января 2012

У меня есть глобальная функция, которая отправляет запросы на почту в мой API, она выглядит следующим образом:

function sendRequest(method,params,callback,cache,override){

    var cacheObject = null;

    if(override == true){
        window.localStorage.removeItem(method);
    }
    //check if cache exists
    if(cache == true){

        console.log('attempting to find cache');

        var cacheString = window.localStorage.getItem(method);

        if(cacheString){
            //put back into object and return to callback
            cacheObject = JSON.parse(cacheString);

            if(cacheObject){
                console.log('cache found' + cacheString);
            }

            window[callback](cacheObject);
            return true;
        }
    }
    if(cacheObject == null || override == true){

        console.log('sending new request');

        var apiKey =  "";
        var sessionKey = null;
        sessionKey = window.localStorage.getItem("session_key");

        var params2 = {
            api_key: apiKey,
            session_key: sessionKey
        }

        var object = $.extend({}, params,params2);    

        var url = apiUrl+method;
        var p = jQuery.param(object);

        //    console.log(url);
        //    console.log(p);

        $.mobile.showPageLoadingMsg();     
        $.post(apiUrl+method,p,function(d) {

            $.mobile.hidePageLoadingMsg();  
            //        console.log(d.success);
            //        console.log(d.message);

            var obj2 = d.data;
            var dataString = JSON.stringify(obj2);

            if(cache == true){

                console.log('updating cache');

                window.localStorage.removeItem(method);

                window.localStorage.setItem(method,dataString);
            }

            console.log(dataString);

            if(d.success == true){
                window[callback](d.data);
            }
            else{
                if(d.message != null){
                    alert(d.message);
                }  
            }
        },'json')
        .error(function(xhr) {

            console.log(xhr.status);
            var status = xhr.status;
            $.mobile.hidePageLoadingMsg();  

            if(status == 400){
                window.localStorage.clear();
                location.href='index.html';

            }
        });

        return true;
    }   
    return false;                
}

Это работало нормально, пока я не поместил свой специфичный для страницы javascript для страниц в пространство имен jquery, основываясь на модели, найденной здесь http://jacob4u2.posterous.com/documentready-with-jquery-mobile. У меня есть страница входа в систему и прикрепленный JS выглядит следующим образом

(function($, ns) {
    function loginPage() {
    };

    loginPage.prototype.init = function($page, pageDom) {

        $('#login_button').click(function() {
            var params = {
                    email : $('#email').val(),
                    password : $('#password').val()

                }

            //test is the callback function that should fire via window[callback]
            sendRequest('login',params,test);

        });

    };

    ns.pages = ns.pages || {}; 
    ns.pages.login = new loginPage();

    function test(){
        alert('callback successful');
    }
}(jQuery, MYAPP));

но я всегда получаю ошибку, что функция окна [обратного вызова] не определена. Также я не могу просто вставить функцию за пределы пространства имен в глобальную область, потому что весь смысл состоит в том, чтобы JS был модульным для каждой страницы.

Ответы [ 2 ]

2 голосов
/ 26 января 2012

Синтаксис window[callback]() предполагает, что callback будет строкой, представляющей имя функции, которая находится в области видимости окна. Вы передаете функцию (test) вместо строки, и эта функция не определена в области видимости окна.

Один из способов исправить это - отредактировать вашу sendRequest функцию, чтобы изменить:

window[callback](cacheObject);

До:

if(typeof callback === 'function'){
   callback(cacheObject);
}
else if(typeof callback === 'string'){
    window[callback](cacheObject);
}

И

if(d.success == true){
    window[callback](d.data);
}

До:

if(d.success == true){
    if(typeof callback === 'function'){
       callback(d.data);
    }
    else if(typeof callback === 'string'){
        window[callback](d.data);
    }
}

Эти изменения позволят передавать функции непосредственно в качестве обратного вызова и не будут нарушать существующие области кода, где вы в данный момент передаете строку.

2 голосов
/ 26 января 2012

Как вы, вероятно, можете видеть, вы получаете эту ошибку, потому что ваш обратный вызов не существует в области действия объекта window.

Попробуйте обновить функцию sendRequest, чтобы вызвать обратный вызов следующим образом:

if ($.isFunction(callback)) {
    callback.call(window, d.data);
}

Чтобы сделать это, убедитесь, что значение callback является функцией, и вызовите обратный вызов, установив область выполнения обратного вызова на значение окна и передав d.data в качествеАргумент обратного вызова.

Как указал JAAulde, вы можете не захотеть выполнять обратный вызов в области действия window, и вы можете вообще не захотеть изменять его область выполнения.В этом случае это будет делать:

if ($.isFunction(callback)) {
    callback(d.data);
}     
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...