1

I have looked through this example code:

function findItem() {
    var item;
    while(item_not_found) {
        // search
    }
    return item;
}

var item = findItem();
// do something with item
doSomethingElse();

And am trying to get my google chrome extension's code to be in the same format (synchronous).

So far I have

var token = chrome.storage.local.get('token', function (result) {
  var tokens = result.token;
  alert("IN: " + tokens);
  return tokens;
});
alert(token);

But, this doesn't work. It never prints the alert in the function at all, and the print that does appear says that token is undefined.

This asynchronous code worked:

chrome.storage.local.get('token', function (result) {
  var tokens = result.token;
});

But I need to get that value of tokens first, then move on with the other code.

4
  • 3
    You don't. You cannot convert an async function to synchronous execution, but you can change the synchronous call into an asynchronous one. Commented Nov 8, 2015 at 19:04
  • I am sorry, but I don't fully understand what that would look like. I am open to a different approach that achieves the same ends. Commented Nov 8, 2015 at 19:08
  • 1
    Just put the code that depends on the value into the callback. There are tons of googlable examples of how to organize asynchronous code execution in javascript. Commented Nov 8, 2015 at 19:10
  • 1
    Use Promises. They make async code feel like synchronous code even though it isn't. Or if you truly need more look at ES6/2015 generators. Commented Nov 8, 2015 at 19:15

1 Answer 1

3

It seems there is a lack of understanding about asynchronous code. The return value really has nothing to do with your example. Based on your description of token being undefined then the .get() method ignores the return value of its callback.

In fact that is the essence of callbacks. The propose of chrome.storage.local.get() is to make the value (in this case result) available only inside the callback function not outside it. The reason for this is that the act of .get() is to do something in the background while your code continues on. It does not wait for anything and so by the time alert() is called the token variable is assigned the return value of .get() which is undefined.

There is no way to break this down without callbacks. Instead put your code inside the callback (see callback hell on why this could be a problem).

As an aside you can make this cleaner by using promises:

function promisedToken() {
  return new Promise(function(resolve, reject) {
    chrome.storage.local.get('token', resolve);
  })
  .then(function(result) {
    var tokens = result.token;
    alert("IN: " + tokens);
    return tokens;
  });
}

promisedToken()
  .then(function(token) {
    alert(token);
  });

For more on callbacks: https://github.com/maxogden/art-of-node#callbacks

Update: Based on the comment I think what your looking for is some guidance on coding style/architecture. Since this is a chrome extension we know the Promises are supported.

There is a library to provide a promise API to chrome.storage.local: https://www.npmjs.com/package/chrome-storage-promise

For clarity it can be done manually with:

In your case make a generic function that returns a promise:

function promisedGet(key) {
  return new Promise(function(resolve, reject) {
    chrome.store.local.get(key, function(result) {
      if (chrome.runtime.lastError)
        reject(chrome.runtime.lastError);
      } else {
        resolve(result);
      }
    });
  });
}

Then in your code a it is a simple matter of:

var promisedResults = promisedGet('token');
var promisedTokens = promisedResults.then(function(result) {
  return result.tokens;
});
promisedTokens.then(function(tokens) {
  alert(tokens);
  return tokens;
});

Which can easily be simplified:

promisedGet('token')
  .then(function(results) {
    alert(results.tokens);
    return results.tokens;
  });

You can make any number of chained results or functions fit for a purpose. The key difference is that any code that needs the result is executed inside a .then() function. If any of those throw an error then the error logic goes in a .catch() function. This style of programming is very expressive and composable.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, but, Is there some way to return a value to a variable then have all code after that execute without putting all the "after that" code inside of promisedToken()?
The question doesn't make much sense in the context of async code nor with promises. I think you need to take a little time and research how callbacks and promises work. It is obvious you like the return/throw control flow of synchronous code and that is a good thing. Promises are a way to simulate the return/throw control flow but with async code. It does however look a little different. This blog post section speaks to what you want.
Added some more prose concerning your specific situation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.