-2

After passing my server side 'data' to the client I am unable to store the 'data' into a variable and receive an undefined.

Why is this happening and how can I resolve this?

The request is made on the client side:

(function () {

    var M;
    var url = '/app/get/metafield';

    fetch(url)
        .then((response) => response.json())
        .then(function (data) {
            filter(data)
        });

    function filter(data) {
        console.log('data :', data) // 25
        M = JSON.stringify(data);

    }

        console.log('M :', M) // undefined
});

This is ther server side code:

  app.get('/app/get/metafield', function (req, res, next) {

               function (error, response, body) {
                    var data = JSON.parse(body)
                    var M = data.metafields[0].value;
                    return res.json(M);
                })

    });
The1987
  • 45
  • 4
  • 12
  • My question though similiar to the question you posted I feel is different as I was asking more about saving the information and calling it globally / how the scope would work with fetch(); – The1987 Jun 01 '19 at 01:24

2 Answers2

1

You should try to run the console.log within the .then() block instead. This is because http requests are asynchronous operations, hence on your above block of code, the line with console.log('M :', M) will be executed before the request is completed and returned.

Therefore, you should add the console.log() statement within that filter function you have defined, such that the console.log() will be executed after the promise has been fulfilled.

fetch(url)
  .then((response) => response.json())
  .then(function (data) {
    filter(data);
    console.log(data);
  });

function filter(data) {
  console.log('data :', data) // 25
  M = JSON.stringify(data);
  console.log('M :', M)
}
wentjun
  • 40,384
  • 10
  • 95
  • 107
1

The problem here is that the fetch call is async, which means that you won't really know for sure when it's going to complete. Instead, if you want any data that depends on the result of calling fetch, you have to chain it to the callback.

You can think about it like this:

  1. I tell my friend to go fetch a URL, but instead of waiting until he's done, I give him instructions (the callback) on what to do when he's done and then I can work on something else in the meantime. The instructions also contains an access to the variable M that he's to update when he's done.

  2. I don't know when he's going to finish, so I can't depend on the value of M being the fetched data for anything I want to do. So if I want something that depends on the fetched data, I have to include it in the instructions.

The remedy is to attach another callback to the Promise chain. You can do this in a functional-programming style:

fetch(url)
    .then((response) => response.json())
    .then(filter)
    .then(process);

function filter(data) {
    console.log('data :', data) // 25
    return JSON.stringify(data);
}

function process(data) {
    ...
}

You can read more about Promise chaining here:

NB: It's generally not a good idea to use global variables for heavily async code. You already realized the reason; it's hard to know when the variable is going to be set to what value because there's no guarantees about the execution order of the async functions. The better way is to pass around the data that you need to use, like I did above with process(data). This is called a pure function because no variables outside the function are touched, all it does is take the input parameters and transforms it to the returns value.

michael
  • 26
  • 2