0

I tried looking at other questions but I can't find a proper solution. I'm retrieving a GET response and I'm storing it into a variable, then I'm parsin that array in order to find daily occurrences. The code works, but once it reaches the forEach it complains with:

Cannot read property 'forEach' of undefined

. Here's my code:

var myObj;
fetch('https://blashblashblash.com?param1')
.then(res=>res.json())
.then(data=>myObj= data)
.then(() => console.log(myObj));

var myRes = [];

myObj.forEach(function (elem) {
    var date = elem.CreationDate.split(' ')[0];


    if (myRes [date]) {
        myRes [date] += 1;
    } else {
        myRes [date] = 1;
    }
});

That's the content of myObj once it finished:

[{Id, Var1, Var2, CreationDate},
{1, 123, Var2, 2020-12-11},
{2, 1234, Var2, 2020-12-12},
{3, 12345, Var2, 2020-12-12},
{4, 1234, Var2, 2020-12-13},
{5, 321, Var2, 2020-12-15},
{6, 3214, Var2, 2020-12-15},
{7, 5432, Var2, 2020-12-16}]

where am I wrong? If I'm executing the code in different steps it works correctly.

EDIT: Here's my updated code:

var myObj;
var myRes= [];
fetch('https://blashblashblash.com?param1')
.then(res=>res.json())
.then(data=>myObj= data)
.then(() => {
myObj.forEach(function (elem) {
    var date = elem.CreationDate.split(' ')[0];
    if (myRes[date]) {
        myRes[date] += 1;
    } else {
        myRes[date] = 1;
    }
});

});

var finalResult= {};
dates.forEach(date => {
    if(!myRes.hasOwnProperty(date)) {
        finalResult[date] = 0;
    } else {
        finalResult[date] = myRes[date];
    }
    return finalResult;
});

If I'm executing the whole my finalResult is empty, while if I'm executing it in blocks it works. If I'm inserting the myRes =[] inside the last .then it complains it can't find it. Where am I wrong?

7
  • 1
    You can't return the data from a fetch like this. Either put everything relying on myObj in a then, or use aysnc/await. Commented Dec 17, 2020 at 11:49
  • but this is working correctly if I'm executing the code in two steps. How can I solve? Commented Dec 17, 2020 at 11:49
  • 1
    Does this answer your question? How do I return the response from an asynchronous call? Commented Dec 17, 2020 at 11:49
  • @evolutionxbox I tried but I cannot understand how to solve. In need to perform some operations on that object once I have retrieved the values in it Commented Dec 17, 2020 at 11:50
  • 1
    You can. Either do the operations inside an attached then, or await the fetch. Commented Dec 17, 2020 at 11:52

2 Answers 2

1

Edit

Duplicated: you might prefer this answer.

Edit: accessing response from outside of then()

Short answer:

You can't.

Long answer:

What you are doing is an asynchronous operation. It means that we don't know how long it will take.

Given an example code below, let's say fetch() takes 5 seconds to complete.

fetch('https://blashblashblash.com?param1').then(doOtherThings);

someTaskAfterFetch();

console.log('Done');

How long will it take until you see 'Done' in console after you run this code? The answer is immediately.

What's happening?

Let's see what happens.

    ===       fetch(url).then(doOtherThings) --> 'Start' fetching, without waiting for result.
     |               |
     |               |                       --> You expect fetch to be done here, which will not happen.
     |               |
     |        someTaskAfterFetch()           --> At this moment you see no fetch result.
almost 0 sec         |
     |               |
     |        console.log('Done')
     |               |
    ===       'Done' is printed
     |               |
     |               |
about 5 sec   (in some future)
     |               |
     |               |
    ===       **Fetch completed**             --> Fetch is finished here.
                     |
              doOtherThings(result)           --> doOtherThings, which we passed to `then()` will be run here.

Execution starts with fetch(url).then(doOtherThings) at line 1.

Then immediately continues to someTaskAfterFetch() at line 2.

Right after that, moves to console.log('done').

In a near future(about 5 seconds after), the fetch you started finally completes, and doOtherThings is called with the result.

How to deal with the result?

You have to separate calling and waiting when thinking about an asynchronous task. You started a fetch task by calling fetch() but didn't wait for the result.

To handle the fetch result:

  • You can wait until a task finishes(async/await)
  • Or tell what to do when fetch is completed.

Using then() is the second approach. You can pass all of your result handling code to then().

For more detailed answer, you might like this.


In your code,

fetch('https://blashblashblash.com?param1')
.then(res=>res.json())
.then(data=>myObj= data)
.then(() => console.log(myObj));

This line will return immediately.

Right after that,

myObj.forEach(function (elem) {
    var date = elem.CreationDate.split(' ')[0];


    if (myRes [date]) {
        myRes [date] += 1;
    } else {
        myRes [date] = 1;
    }
});

The forEach will be called.

At that moment, requesting a fetch job is quickly finished before the forEach. However, the fetching itself might not have finished at that time.

The functions you passed to the following then() calls will be launched after the fetching is successfully finished.

You can pass your forEach code to the then() method:

var myObj;
fetch('https://blashblashblash.com?param1')
.then(res => res.json())
.then(data => myObj = data)
.then(() => console.log(myObj));
.then(() => {
    var myRes = [];

    myObj.forEach(function (elem) {
        var date = elem.CreationDate.split(' ')[0];


        if (myRes [date]) {
            myRes [date] += 1;
        } else {
            myRes [date] = 1;
        }
    });

    // And other stuffs to do with myRes.
})
Sign up to request clarification or add additional context in comments.

5 Comments

This is a duplicate of stackoverflow.com/questions/14220321/… Please may you mark it as such?
Updated my question with an issue
@Potados how can I access my variable from outside? Like I described in my edit
Thank you very much! I solved using a setTimeout()
@thranduil90 that will only cover up the issue. It will fail when the fetch takes longer than the timeout.
1

Because your fetch & then is a async operation, you need to execute forEach in then function like below:

var myObj;
fetch('https://blashblashblash.com?param1')
.then(res=>res.json())
.then(data=>myObj= data)
.then(() => {
    console.log(myObj);
    var myRes = [];

    myObj.forEach(function (elem) {
        var date = elem.CreationDate.split(' ')[0];


        if (myRes [date]) {
            myRes [date] += 1;
        } else {
            myRes [date] = 1;
        }
    });
});

8 Comments

This is a duplicate of stackoverflow.com/questions/14220321/…. Please may you mark it as such?
thanks! But I then need to access the myRes element and in that case it says it's not defined. How can I access it afterwards?
@thranduil90 You can access myRes in the then(() => { ... }) block.
@thranduil90 Not outside the then you can't.
Can I declare it near myObj and access it afterwards?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.