Issues storing JSON data in sessionStorage

1.4k Views Asked by At

I'm trying to utilize HTML5 sessionStorage to retain some data previously retrieved from an external API, so as to cache the data when it is later called again, rather than making a connection to retrieve redundant data that has already been retrieved this session.

function getItemWithTooltip(item_id, div_id) {
var xmlhttp2 = new XMLHttpRequest();
var url2 = "https://api.guildwars2.com/v2/items/"+item_id;

xmlhttp2.onreadystatechange=function() {if (xmlhttp2.readyState == 4 && xmlhttp2.status == 200) {parseItemTooltip(xmlhttp2.responseText);}};
xmlhttp2.open("GET", url2, true);
//xmlhttp2.send();

var item;

var cache_enabled = true;
// Cache results for quicker page loads
if (cache_enabled == true){
    if (Storage !== void(0)) {
        // Retrieve data (if stored)
        if (sessionStorage[String(item_id)]) {
            //item = JSON.parse(sessionStorage.getItem(String(item_id)));
            item = JSON.parse(sessionStorage[item_id.toString()]);
            //window.alert("sessionStorage: Retrieved");
            //alert(typeof (item));
            //alert(item);
        }
    }
}

if (item == null){
    xmlhttp2.send();
}

  function parseItemTooltip(response) {
    //var item = JSON.parse(response);

    if (item == null){
        // Store data
        if (cache_enabled == true){sessionStorage.setItem(item_id.toString(), JSON.stringify(response));}
        //sessionStorage.setItem(String(item_id), item);
        //if (cache_enabled == true){sessionStorage.setItem(String(item_id), response);}
        //window.alert("sessionStorage: Stored");
        item = JSON.parse(response);
    }
    //..More code here that was not relevant and removed to save space..
  }
}
2

There are 2 best solutions below

0
On

Well after bugging-out at my code for another hour, I finally figured out the issue, and it was something stupid simple, like it usually is.

My answer was to reverse these two lines:

    getItemWithTooltip(item.id, div_ID);
    document.getElementById("id01").innerHTML = out;

To this:

    document.getElementById("id01").innerHTML = out;
    getItemWithTooltip(item.id, div_ID);

Reasoning: It was trying to fill in the div before it was being created. Previously it didn't matter, because it was filled in while waiting for the remote server response, however now with data cached into sessionStorage, it was retrieved so fast, that the order did become a factor. Always good to pay attention to logical order of progression.

Thank you to everyone who contributed to debugging this. Much thanks, and appreciation! Quick responses, and friendly people. Made for a great time for a first-timer on this website.

17
On

I think the issue has something to do with the fact that you JSON.stringify the response when storing it. The response is already a string, so that's going to "double-stringify" it and when you parse it you will only get the original string back.

You do both JSON.stringify AND JSON.parse on the response text. This makes no sense for JSON, you should only need to do one of these. If you stringify a string, it will become "double-stringified". If you try to parse an object, you will get error because JSON.parse requires a string.

Lets say your response text looks like this:

'{"property":"value"}'

It's a string. Now, when you stringify it, it will become this:

'"{\"property\":\"value\"}"'

When you parse this, like you do when getting it from sessionStorage, you will only get the original string back. You would have to parse it again to get the object you want.

When you do that parse on the response text directly, you correctly get the object:

{
  property: "value"
}

So what you need to do is to store the response text in sessionStorage without stringifying it.


You're also only invoking parseItemTooltip in the state change handler for the request, so it never gets invoked when you get the cached item. Looking at your full code, I can see that you do basically everything in this function so you need to invoke it explicitly when not performing the request.