简体   繁体   English

如何从函数/实例外部访问变量

[英]how to access a variable from outside a function/instance

I have this very simple JavaScript code that should return a Fullname using parameters firstname and lastname All works fine when I alert out the fullname within the function. 我有这个非常简单的JavaScript代码,应该使用参数firstnamelastname返回全名。当我在函数中提醒全名时,All都可以正常工作。 But I'm struggling how to make the fullname variable accessible from outside the function/instance? 但是我正在努力如何使fullname变量可以从函数/实例外部访问?

here's my code: 这是我的代码:

var getName = function () {

    this.name = function (firstname, lastname, success) {
        var fullName = firstname + " " + lastname;
        success(fullName);
    };

};


var test = new getName();

test.name("John", "Smith", function (output) {
    var fullname = output;
    alert(fullname); //this works fine
    return fullname; // I need this variable to be accessed from outside this function
});

var myName = fullname; //I need to create the variable here
alert(myName); //this does not work

Here's Fiddle 这是小提琴

Thank you very much for your help. 非常感谢您的帮助。

Edit: I'm building an iPad app where I'm using cordova and javascript plugins. 编辑:我正在构建一个iPad应用程序,其中我使用了cordova和javascript插件。 One of the plugin gives me access to the file inside the device. 其中一个插件使我可以访问设备内部的文件。 Now, I need to be able to get the path and use it outside the callback so that I can use anywhere in the scope: 现在,我需要能够获取路径并在回调之外使用它,以便可以在范围内的任何地方使用:

Here's the plugin code: 这是插件代码:

var FileManager = function(){

this.get_path = function(todir,tofilename, success){
        fail = (typeof fail == 'undefined')? Log('FileManager','read file fail'): fail;
        this.load_file(
            todir,
            tofilename,
            function(fileEntry){

                var sPath = fileEntry.toURL();
                success(sPath);
            },
            Log('fail')
        );

    }


    this.load_file = function(dir, file, success, fail, dont_repeat){
        if(!dir || dir =='')
        {
            Log('error','msg')('No file should be created, without a folder, to prevent a mess');
            fail();
            return;
        }
        fail = (typeof fail == 'undefined')? Log('FileManager','load file fail'): fail;
        var full_file_path = dir+'/'+file;
        var object = this;
        // get fileSystem
        fileSystemSingleton.load(
            function(fs){
                var dont_repeat_inner = dont_repeat;
                // get file handler
                console.log(fs.root);
                fs.root.getFile(
                    full_file_path,
                    {create: true, exclusive: false},
                    success,

                    function(error){

                        if(dont_repeat == true){
                            Log('FileManager','error')('recurring error, gettingout of here!');
                            return;
                        }
                        // if target folder does not exist, create it
                        if(error.code == 3){
                            Log('FileManager','msg')('folder does not exist, creating it');
                            var a = new DirManager();
                            a.create_r(
                                dir,
                                function(){
                                    Log('FileManager','mesg')('trying to create the file again: '+file);
                                    object.load_file(dir,file,success,fail,true);
                                },
                                fail
                            );
                            return;
                        }
                        fail(error);
                    }
                );
            }
        );
    };
}

and here's how I use it: 这是我的用法:

    var b = new FileManager(); // Initialize a File manager

    b.get_path('Documents','data.json',function(path){
        myPath = path;
        console.log(myPath); //this gives me the path of the file in the console, which works fine
        return myPath; //I return the path to be accessed outside
    });

    var filePath = myPath; //here I need to access the path variable
    console.log(filePath)// here, the path is undefined and it does not work

    //Since I'm using angular services to retrieve the data from json, I'd like to pass the filePath
  //this is a fraction of code for retrieving data:
  return $resource('data.json',{}, {'query': {method: 'GET', isArray: false}});

  //passing the value does not work
  return $resource(filePath,{}, {'query': {method: 'GET', isArray: false}});

  //even wrapping resource around instance does not work, it breaks the whole app
  b.get_path('Documents','data.json',function(path){
        myPath = path;
        console.log(myPath); //this gives me the path of the file in the console, which works fine
        return $resource(myPath,{}, {'query': {method: 'GET', isArray: false}});
    });

Factory services: 工厂服务:

'use strict';
angular
    .module ('myApp')
    .factory('getMeData', function ($resource) {
        var b = new FileManager(); // Initialize a File manager
        b.get_path('Documents','data.json',function(path){
            myPath = path;
            return myPath;
        });

        //below doesn't work when passing path (it is undefined)
        return $resource(myPath,{}, {'query': {method: 'GET', isArray: false}});

        //when wrapping it around, the app crashes
        b.get_path('Documents','data.json',function(path){
            myPath = path;
            return $resource(myPath,{}, {'query': {method: 'GET', isArray: false}});
        });

        //none of the solution above work

    });

If you have the name function return the result of success then you can use the return from the method. 如果您具有name函数,则返回success的结果,那么您可以使用方法中的return。

Ie

var getName = function () {
    this.name = function (firstname, lastname, success) {
        var fullName = firstname + " " + lastname;
        return success(fullName);
    };

};


var test = new getName();

var myName = test.name("John", "Smith", function (output) {
    var fullname = output;
    alert(fullname); //this works fine
    return fullname; // I need this variable to be accessed from outside this function
});
alert(myName);

Define fullname outside the callback. 在回调之外定义fullname

var getName = function () {

    this.name = function (firstname, lastname, success) {
        var fullName = firstname + " " + lastname;
        success(fullName);
    };

};


var test = new getName();
var fullname;
test.name("John", "Smith", function (output) {
    fullname = output;
    alert(fullname); //this works fine
    return fullname; // I need this variable to be accessed from outside this function
});

alert(fullname);

Hope it helps. 希望能帮助到你。 Fiddle 小提琴

If async required: 如果需要异步:

Assuming the actual source of the code is an async one, now confirmed from your comment, you should simply process the result within the callback. 假设实际的代码源是一个异步代码,现在已从您的注释中确认,您应该只在回调中处理结果。 The value is simply not available outside of the callback as the result arrives later. 该值在回调之外根本不可用,因为结果稍后到达。

The answers by @Jim and @bestmike007 will not work with an async operation as it returns a value from inside a callback which may occur long after the function is run. @Jim和@ bestmike007的答案不适用于异步操作,因为它从回调内部返回一个值,该回调可能在函数运行很长时间后发生。 (note: @bestmike007 does have an improved answer linked in a comment). (注意:@ bestmike007确实在注释中链接了一个改进的答案)。

eg Look at what happens here: http://fiddle.jshell.net/y1m36w9p/1/ or here http://jsfiddle.net/TrueBlueAussie/opczeuqw/1/ 例如,看看这里发生了什么: http : //fiddle.jshell.net/y1m36w9p/1/或这里http://jsfiddle.net/TrueBlueAussie/opczeuqw/1/

The only way to work with async code is in an async manner. 使用异步代码的唯一方法是异步方式。 That means you can only handle the result inside the callback: 这意味着您只能在回调内部处理结果:

// Get the fullname asyc and process the result
test.name("John", "Smith", function (fullname) {
    alert(fullname); // you can only work with the result in here
});

An alternative is to return a jQuery promise from getName.name() , but the end result will still be a callback to do the work, but this time it would look like this: 另一种方法是返回一个jQuery promisegetName.name()但最终的结果仍然是回调做的工作,但是这一次它是这样的:

test.name("John", "Smith").done(function(fullname){
    alert(fullname); // you can only work with the result in here
});

but this is more code and complication for no extra benefit at this time. 但这是更多的代码和复杂性,暂时没有额外的好处。

For your specific updated example code: 对于您特定的更新示例代码:

I am not familiar enough with Angular to confirm this, and would need to see how getMeData is called, but you should use another callback as a parameter to the getMeData function you register: 我对Angular不够熟悉,无法确认这一点,因此需要了解如何getMeData ,但是您应该使用另一个回调作为注册的getMeData函数的参数:

'use strict';
angular
    .module ('myApp')
    .factory('getMeData', function ($resource, callback) {
        var b = new FileManager(); // Initialize a File manager
        b.get_path('Documents','data.json',function(path){
            callback($resource(path,{}, {'query': {method: 'GET', isArray: false}}));
        });
    });

If async not required (obsolete option) 如果异步不需要 (废弃的选项)

If (as a previous contradictory comment below said) this was not mean to to be async, then do not use callbacks at all, just simple functions/methods returning values: http://fiddle.jshell.net/y1m36w9p/2/ 如果(如下面先前的矛盾评论所述)这并不意味着要异步,那么根本不要使用回调,只需返回值的简单函数/方法即可: http : //fiddle.jshell.net/y1m36w9p/2/

eg 例如

var getName = function () {
    this.name = function (firstname, lastname) {
        return firstname + " " + lastname;
    };
};

// Create a instance of the getName class
var test = new getName();

// Get the fullname asyc and process the result
var fullname = test.name("John", "Smith");

// Do what you like with the value returned from the function
alert(fullname); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM