Getting JavaScript promise value

2020-03-06 07:55发布

I have a json file I am trying to read the contents of for use in a script. I am using the following to fetch json:

const json = fetch('Data/my_data.json').then(response => response.json());

When I do this and I look at the json object in the console I see it is a returned promise (resolved status) containing the actual json object from the file. You can't directly access the promisevalue though. you have to use a then statement again so I used this:

json.then(function(getData){metaData = getData;});

The metaData object is not set to the value of the original promise. It is unset until a later time when the 2nd then completes. The information is already available though in the originally returned promise.

Is it possible to get the original promisevalue without the 2nd then statement or am I accessing the promise incorrectly with the 2nd then statement.

Thanks for any insight!

2条回答
男人必须洒脱
2楼-- · 2020-03-06 08:18

Based on the documentation here:

https://developer.mozilla.org/en-US/docs/Web/API/Response

You're most likely looking for this syntax:

fetch('Data/my_data.json')
  .then(response => response.json())
  .then((json) => {
    console.log('this is the json data', json)
  })

The Response object is designed to assist with streaming data responses. In order to get the actual data you need to call the appropriate function for the format you're looking for. All of these functions return another Promise which allows you to chain again.

If you're concerned about syntax using the Promise.then, you can extract it a bit to do something like:

  function handleResponse(json) {
    console.log('this is the json data', json)
  }

  fetch('Data/my_data.json')
    .then(response => response.json())
    .then(handleResponse)

If you want to go further and have access to the original response, it would look like this:

function handleResponse(response) {
   console.log('response status: ', response.status)

   response.json().then((json) => {
      console.log('what should I do with this json?', json, response)
   })
}

fetch('Data/my_data.json').then(handleResponse)

At the end of the day, the API is designed for ReadableStreams and thus uses Promises in every step of the way. In order to get the data you want out of the Fetch API, you have to play by the rules of streaming.

查看更多
Ridiculous、
3楼-- · 2020-03-06 08:36

Is it possible to get the original promisevalue without the 2nd then statement or am I accessing the promise incorrectly with the 2nd then statement.

You must use either .then() or await to get the data out of the promise. The data is retrieved asynchronously so the only wait to get it out of the promise is with .then() or await. And, if using await, it would have to be inside an async function.

While promises and async/await are helpful for managing asynchronous operations, they cannot change the fact that the data is retrieved asynchronously and will not be available synchronously. So, you have to use asynchronous tools to get to the data. In this case, that's .then() or await.

And, to use await, you have to be in an environment that supports it. Modern browsers do support it (and you're already using fetch() which requires a semi-modern browser), but not some of the older browsers still in use by some so that is a consideration. In this case, you should probably use .then().


Also, note that in this coding structure:

json.then(function(getData){metaData = getData;});

where you're assigning the data from the promise to a higher scoped variable is nearly always a warning sign that you're attempting to use the data in a scope in which you don't know the timing for when the data is actually available and doing something wrong.

The ONLY scope that you can safely use the data is INSIDE the .then() handler or in a function that you call from there and pass the data to. Don't assign it to a higher scope and then try to just blindly use in that higher scope. You won't have any idea when the data is actually valid. You only know that timing information inside the .then() handler.

json.then(function(data){
    // use the data here
    // write the code in here that uses the data
    // or call some function here that you pass the data to
    processData(data);
});
// can't use the data here (it's not yet available)

For further explanation of this issue see: How do I return the response from an asynchronous call?

查看更多
登录 后发表回答