Question

My theory might be a bit weak asking this, so feel free to let me know.

This code is part of a browser plugin using Kango framework. Basically I have code that generates a random string that's a userID. I also have another function that sets up a big ole JSON. It looks something like this:

function createJSON() {
data = {};
data["userID"] = generateID();
}

function generateID() {
kango.invokeAsync('kango.storage.getItem', 'userID', function(data) {
    uid = data;

    if (!uid) {
      console.log("uid doesn't exist, creating uid!");
      kango.invokeAsync('kango.storage.setItem', userID, function(data) { return data; });
    } else {
      console.log("uid found!: " + uid);
      return uid;
    }

    return data;
  });
}

kango.invokeAsync docs are here. My understanding is it works a bit like an async ajax call and in that sense it doesn't return just in time for when I'm trying to assign its value to data["userID"].

I think I can solve this by doing doing the userID call first and then using it's callback(a bit vague on the terminology here) to go ahead and add to the data array.

I have no clue if that's the right way to do it though. How do I get a return of an async function to work with?

Was it helpful?

Solution

You can't do it like this because of the async nature of generateID(). It will return BEFORE the async call has finished, thus the data is not available:

data["userID"] = generateID();

Instead, you have to use a callback like this:

generateID(function(val) {data["userID"] = val;});

function generateID(callback) {
kango.invokeAsync('kango.storage.getItem', 'userID', function(data) {
    uid = data;

    if (!uid) {
      console.log("uid doesn't exist, creating uid!");
      kango.invokeAsync('kango.storage.setItem', userID, function(data) { callback(data); });
    } else {
      console.log("uid found!: " + uid);
      callback(uid);
    }

  });
}

When using asynchronous functions, you CANNOT use normal sequential programming. Instead, you have to continue your execution flow in the completion callback because ONLY then is the result of the async function known.

Thus, you won't be able to call createJSON() and return the desired value from that. If any code after createJSON() needs the results, it also has to be in a callback.

OTHER TIPS

Take a look more closer to invokeAsync examples from documentation.

In your code you have two mistakes with invokeAsync and kango.storage.setItem call:

// 1. Second argument should be string 'item name'
// 2. Third argument should be 'item value'
kango.invokeAsync('kango.storage.setItem', userID, function(data) { callback(data); });

You should use kango.storage.setItem with invokeAsync in this way:

kango.invokeAsync('kango.storage.setItem', 'userID', '123');    

So, result code will be like this:

function generateID(callback) {
    kango.invokeAsync('kango.storage.getItem', 'userID', function(uid) {
        if(!uid) {
            kango.console.log("uid doesn't exist, creating uid!");
            uid = '123'; // TODO: replace with your ID generation algorithm
            kango.invokeAsync('kango.storage.setItem', 'userID', uid);
        }
        else {
            kango.console.log("uid found!: " + uid);
        }
        callback(uid);
    });
}

data = {};
generateID(function(uid) {
    data["userID"] = uid;
});
function createJSON() {
  data = {};
  generateID(function(id) {
    data["userID"] = id;
  });
}

function generateID(callback) {
  kango.invokeAsync('kango.storage.getItem', 'userID', function(data) {
  uid = data;

  if (!uid) {
    console.log("uid doesn't exist, creating uid!");
    kango.invokeAsync('kango.storage.setItem', userID, function(data) { callback(data); });
  } else {
    console.log("uid found!: " + uid);
    callback(uid);
  }

  callback(data);
});
}

Would this work for you?

You can't return an object from an async call. Rather create another function and pass the callback object to it.

// some code
if (!uid) {
  console.log("uid doesn't exist, creating uid!");
  kango.invokeAsync('kango.storage.setItem', userID, function(data) { 
    getData(data); 
  });
} else {
  console.log("uid found!: " + uid);
  getData(uid);
}

function getData(data) {
    // Use data here.
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top