1

This kind of question is very frequent, but I could not make what I want. My code look like this. Some pubKeyProfiles are stored in chrome.storage, and I want my function getProfile to return one of them.

getProfile(keyPairId){

    var profile = null;

    chrome.storage.local.get({ pubKeyProfiles : [] }, function (result) {
        var pubKeyProfiles = result.pubKeyProfiles;
        for (var i = 0; i < pubKeyProfiles.length; ++i) {
            if(pubKeyProfiles[i].pubKey.keyId === keyPairId){
                profile = pubKeyProfiles[i];
            }
        }
    });

    console.log(profile);
}

After reading How to return value from an asynchronous callback function?, I tried the following code :

getProfile(keyPairId){

    var profile = null;

    function foo(fn){
        chrome.storage.local.get({ pubKeyProfiles : [] }, function (result) {
            var pubKeyProfiles = result.pubKeyProfiles;
            for (var i = 0; i < pubKeyProfiles.length; ++i) {
                if(pubKeyProfiles[i].pubKey.keyId === keyPairId){
                    profile = pubKeyProfiles[i];
                    fn(profile);
                }
            }
        });
    }

    foo(function(profile){
        return profile;
    });

    console.log(profile);
}

But, as I am dealing with an asynchronous function, profile remains null whatever I try.

My question is : how can I make the function getProfile return profile ??

Community
  • 1
  • 1
little-dude
  • 1,544
  • 2
  • 17
  • 33
  • 1
    Forget `return` when dealing with async code. Instead of returning from the function you're passing in, resume your program flow from there. – bfavaretto May 23 '13 at 17:47
  • 3
    Remove the `return profile` from the callback, and put your `console.log();` in its place. The point of the callback is that it is the continuation of the flow that happens after the response returns. –  May 23 '13 at 17:47
  • You can't return it without blocking and waiting for the async call to complete, which is a bad practice that you should avoid. – Paul May 23 '13 at 17:47
  • 1
    You can't return `profile` from `getProfile`, because `getProfile` returns sooner that `profile` is available. Period. – John Dvorak May 23 '13 at 17:48
  • 1
    possible duplicate of [how to return value from callback function](http://stackoverflow.com/questions/6847697/how-to-return-value-from-callback-function) ...the answer in the question you linked very clearly shows the `alert()` inside the callback. –  May 23 '13 at 17:48
  • possible duplicate of [How to return the response from an AJAX call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call) – bfavaretto May 23 '13 at 17:54
  • Thanks for answers. Indeed there are similar topics, but as I could not find the solution I wanted I opened this one. @squint yes the `alert` is in the function, but I wanted to `return` and not `alert` my variable. @JanDvorak thanks for this clear&concise explanation. – little-dude May 24 '13 at 05:53
  • @emmasculateur: Yes, I know. The first words of the linked answer are *"this is impossible"*. –  May 24 '13 at 13:05

1 Answers1

3

passing a callback to your function is a better idea.

var getProfile = function (keyPairId, callback) {
    chrome.storage.local.get({ pubKeyProfiles : [] }, function (result) {
        var pubKeyProfiles = result.pubKeyProfiles, profile;
        profile = pubKeyProfiles.filter(function (pubKeyProfile) {
            return pubKeyProfile.pubKey.keyId === keyPairId
        })[0];

        callback(profile);
    });
};

getProfile(keyPairId, function (profile) {
    //do something with profile here
});
Orlando
  • 9,374
  • 3
  • 56
  • 53
  • 1
    Thank you :) I'm disappointed to have to make getProfile asychronous, but it seems I have no choice. Btw, should `callback(profile)` be inside the callback function of `chrome.storage.local.get` ? Because here, `profile` is null. Another question is coming. I didn't know array.filter, but it seems to an asynchronous function that return a value (an array in this case). It means it is possible ! Why is different in my case ? – – little-dude May 24 '13 at 09:02
  • 1
    yes sorry about that, `callback(profile)` should be inside profile (fixed). filter is a synchronous function, the `function` i'm passing to filter is the compare function not a callback, https://developer.mozilla.org/en/docs/JavaScript/Reference/Global_Objects/Array/filter, you can use the same code in your question (use a for loop instead of filter). – Orlando May 25 '13 at 18:05
  • 1
    and well about why you need to make your function asynchronous is not your fault, you need to use `chrome.storage` and that library is asynchronous (in deep, it uses html5 localstorage, and that API is asynchronous). If one piece of your function is asynchronous, then all your function needs to be asynchronous, you can't do much about it. – Orlando May 25 '13 at 18:08