最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

access to a variable "outside" of a callback function in javascript - Stack Overflow

programmeradmin4浏览0评论
loadJSON(path, callback) {
    console.log("path: " + path); 
    var xobj = new XMLHttpRequest();
        xobj.overrideMimeType("application/json");
    xobj.open('GET', path, true);
    xobj.onreadystatechange = function () {
          if (xobj.readyState == 4 && xobj.status == "200") {
            callback(xobj.responseText);
          }
    };
    xobj.send(null);  
 }

Above is a function to access a json file locally. Then from `foobar()' parse the data retrieved. However from "outside" of call back function, the variable "json" cannot be accessed. I had searched similar SO questions and async concepts but still was not able to figure a way to resolve it.

function foobar() { 
    var json;
    loadJSON("data.json", function(response) {
        json = JSON.parse(response);
        console.log(json[0].name); // Successfully shows the result
    });
    console.log(json[0].name); // TypeError: json is undefined
}

Is there a way to access the variable "outside" of the callback?

loadJSON(path, callback) {
    console.log("path: " + path); 
    var xobj = new XMLHttpRequest();
        xobj.overrideMimeType("application/json");
    xobj.open('GET', path, true);
    xobj.onreadystatechange = function () {
          if (xobj.readyState == 4 && xobj.status == "200") {
            callback(xobj.responseText);
          }
    };
    xobj.send(null);  
 }

Above is a function to access a json file locally. Then from `foobar()' parse the data retrieved. However from "outside" of call back function, the variable "json" cannot be accessed. I had searched similar SO questions and async concepts but still was not able to figure a way to resolve it.

function foobar() { 
    var json;
    loadJSON("data.json", function(response) {
        json = JSON.parse(response);
        console.log(json[0].name); // Successfully shows the result
    });
    console.log(json[0].name); // TypeError: json is undefined
}

Is there a way to access the variable "outside" of the callback?

Share Improve this question asked Mar 8, 2017 at 8:54 HUKSHUKS 3192 gold badges4 silver badges11 bronze badges 3
  • stackoverflow.com/questions/14220321/… – Gerardo Furtado Commented Mar 8, 2017 at 8:56
  • Possible duplicate of Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference – Andreas Commented Mar 8, 2017 at 8:58
  • 2 Checked both links and now I get a better understanding why it cannot be called 'outside' of the callback, Now I resolved my issue by implementing functions inside loadJSON() but I still don't get how I can access the variable outside of it. I want to know there is a workaround not why. – HUKS Commented Mar 9, 2017 at 0:47
Add a comment  | 

3 Answers 3

Reset to default 9

It's because it's set in Asynchronous mode.

console.log(json[0].name); // TypeError: json is undefined

This code is executed before json is filled. Therefore when you try to access it, it might be still empty. The third argument in this line defines it as Async:

xobj.open('GET', path, true);

You could try to put

xobj.open('GET', path, false);

But it isn't asynchronous anymore and the user will have to wait for the request to end, so it's probably better to make sure to use the 'json' var when the callback method has ben called and not before. Keeping the asynchrnous mode on. For this you'll need to restructure your code.

The link posted by Gerardo Furtado is totally accurate, you should check it.

Edit: As i already stated, and other users too, the async:false is not very good, so i'm editing my answer:

function foobar() { 
    var json;
    loadJSON("data.json", function(response) {
        json = JSON.parse(response);
        // Call another function with json that is now filled with data
        triggered(json);
    });
}

function triggered(json) {
    console.log(json[0].name);
    // Do your work on json
}

This is an older question but it seems to be a common problem. Nowadays, we can use async/await and promises instead of separating our code into callbacks.

With a problem like this, we could just use the fetch API, but consider a scenario where you are using a third party API that uses callbacks instead of promises. You can't control the function, so how can you do this?

This is where promises and async/await come in. You can create a promise of the result and use it outside of the callback.

In OP's scenario, they are running their code in a foobar function. Here, all we need to do is make foobar an async function.

async function foobar() {
  const json = await new Promise((resolve) =>
    loadJSON("data.json", (response) => resolve(JSON.parse(response)))
  );

  console.log(json[0].name); // works!
}

This is especially useful when dealing with third party APIs. Say you have some API that uses callbacks:

XYZLibrary.api("/path/to/xyz", (error, response) => {
  if (error) return console.error(error);
  console.log(response);
});

You can convert the same code to use Promises.

async function main() {
  const response = await new Promise((resolve, reject) =>
    XYZLibrary.api("/path/to/xyz", (error, response) => {
      if (error) return reject(error);
      resolve(response);
    })
  );
  console.log(response);
}
main();

You can even make a wrapper:

async function apiWrapper(path) {
  return new Promise((resolve, reject) =>
    XYZLibrary.api(path, (error, response) => {
      if (error) return reject(error);
      resolve(response);
    })
  );
}
async function main() {
  const response = await apiWrapper("path/to/xyz");
  console.log(response);
}
main();

It is very simple. Declare the json variable outside the function. This gives the variable a global scope. The function is called just to override json and the json can be used anywhere in the script

发布评论

评论列表(0)

  1. 暂无评论