How to run get json and save as a variable, then u

2019-08-23 05:36发布

问题:

I want to parse a JSON file, then store its data in a variable and use it in different part of the code. I think for this purpose I should use $.when().done(). However, I I do not know how to pass data. The following code is not function but it shows what I am trying to achieve.

var myJSON;

function _parseJSON() {
  $.getJSON(settings.json_src).done(function(data) {
    return data;
  });
}

$.when(_parseJSON()).done(function() {
  myJSON = data;
});

function _cacheOptions() {
  console.log(myJSON.data);
};
_cacheDom();
_events();
_render();
....

I need the following happen. 1- get JSON 2- save it in a variable. 3- having the variable available in the code to use its data.

At least the JSON data needs to be ready before few methods run.

Any idea?

Thanks in advance.

回答1:

Well, you could use Promises for chaining instead, and use the data you pass around to do something with that data as you go through your chains.

So, if you want a sample implementation using promises, and handling passed around data, you can look at the following code, it:

  • retrieves a random image
  • passes the image url as a result
  • that image url is then used to preload an image, and returns the image element
  • the image element is then displayed
  • the console.log statement is printed

function retrieveData() {
  return $.when( $.getJSON('https://dog.ceo/api/breeds/image/random')
    .then( data => data.message ) );
}

function retrieveImage( source ) {
  return new Promise( (resolve, reject) => {
    const image = new Image();
    image.addEventListener( 'load', function() {
      resolve( image );
    } );
    image.src = source;
  } );
}

function displayImage( image ) {
  document.getElementById('image-container').appendChild( image );
  return Promise.resolve( true );
}

retrieveData()
  .then( retrieveImage )
  .then( displayImage )
  .then( () => console.log('all done') )
  .catch( err => console.error( err ) );
  
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="image-container"></div>

Since a promise will wait for returned promises to complete (or fail), this all goes after each other, so the log statement will not be printed before the element got displayed.

When 1 step fails, it will jump to the next catch in the chain. In my example, there is only 1 catch (and I am not handling errors from $.getJSON), so if something does go wrong, it should print an error in the console.

You can of course make use of the $.when statement provided by jQuery to do pretty much the same, as it returns a Promise

So applied to your code, you should return the $.getJSON from your parse function, and then chain based on that

var myJSON;

function _parseJSON() {
  // return here, no need returning exactly what you would expect anyhow
  return $.getJSON(settings.json_src);
}

// because you returned, you can chain everything nicely together
$.when( _parseJSON() )
  // don't forget the argument here
  .then(function( data ) { myJSON = data; })
  // and these will only run after the myJSON got set
  .then( _cacheOptions )
  .then( _cacheDom )
  .then( _events )
  .then( _render );

Though I would really suggest not to work with global variables. If you add arguments to the functions you are calling, those functions will become independent from any magical variables, and can stand on their own instead

Note that if any of your chains return a deferred object, it will wait for that deferred object to be completed.

Note that we are not calling the methods ourselves in the chain, we just pass in the function reference, so it can be called in sequence ( so: _events vs _events() )