skip to Main Content

I have a problem with the Javascript code in my Bred Clicker game.

I am working on data saves through text files and the file will not save to the computer ONLY WHEN THE ‘bakers’ ARRAY HAS DATA IN IT. it only saves when there are no dictionaries inside the baker array.

This is my code:

function saveData() {
    var dataToGo = {"money": money, "mps": mps, "mpc": mpc, "currentBred": currentBred, "yeastCost": yeastCost, "yeastType": yeastType, "bredCost": bredCost, "bredMulitplier": bredMulitplier, "bakerCost": bakerCost, "bakers": bakers}; //THE 'bakers' SECTION IS WHERE IT BREAKS.
    var txtFD = dataToGo.map(btoa);
    var txtF = new File([txtFD], "data.txt");
    var a = document.createElement("a");
    var url = URL.createObjectURL(txtF);
    a.href = url;
    a.download = "data.txt";
    document.body.appendChild(a);
    a.click();
    setTimeout(function() {
        document.body.removeChild(a);
        window.URL.revokeObjectURL(url);  
    }, 0); 
}

I tried to solve it by debugging with websites but NOTHING works and it is very annoying.

3

Answers


  1. You are using map() wrong. Its an array method.

    If dataToGo.bakers is the array you should use map() as

    dataToGo.bakers.map(function(element) {
      return newElement;
    })
    
    Login or Signup to reply.
  2. You cannot use .map(btoa) directly on an object. The map method is an array method. btoa converts binary data to base64-encoded ASCII string and you might want to convert your entire JSON string not just parts of it.

    Regarding of the content of bakers array there could be non-Latin1 characters in it, which would cause btoa to throw an error, since it cannot handle Unicode chars out of the Latin1 ones.

    Let’s adjust your saveData() function.

    First we need to convert the object to a JSON string and then encode that string. Also using a more robust method for converting the string to base64 that can handle Unicode characters would be a good idea.

    Adjusted saveData() function:

    function saveData() {
      var dataToGo = {
        "money": money,
        "mps": mps,
        "mpc": mpc,
        "currentBred": currentBred,
        "yeastCost": yeastCost,
        "yeastType": yeastType,
        "bredCost": bredCost,
        "bredMulitplier": bredMulitplier,
        "bakerCost": bakerCost,
        "bakers": bakers
      };
    
      // Converts the object to JSON string.
      var jsonString = JSON.stringify(dataToGo);
    
      // Encodes the JSON string to base64 in a way that handles Unicode characters.
      var encodedString = btoa(unescape(encodeURIComponent(jsonString)));
    
      var txtF = new File([encodedString], "data.txt");
      var a = document.createElement("a");
      var url = URL.createObjectURL(txtF);
      a.href = url;
      a.download = "data.txt";
      document.body.appendChild(a);
      a.click();
    
      setTimeout(function() {
        document.body.removeChild(a);
        window.URL.revokeObjectURL(url);
      }, 0);
    }
    Login or Signup to reply.
  3. I might suggest a decomposed approach. First a pair of serialize and deserialize functions for lossless encoding and decoding your app state –

    function serialize(appData) {
      return btoa(JSON.stringify(appData))
    }
    
    function deserialize(str) {
      return JSON.parse(atob(str))
    }
    

    Isomorphism –

    deserialize(serialize(X)) == X
    

    Next, a pair of functions to write and read files –

    async function write(file) {
      const url = URL.createObjectURL(file)
      const a = document.createElement("a")
      a.href = url
      a.download = file.name
      a.click()
      await new Promise(r =>
        setTimeout(() => { r(URL.revokeObjectURL(url)) }, 0)
      )
    }
    
    async function read(url) {
      const res = await fetch(url)
      const buffer = await res.arrayBuffer()
      return new TextDecoder("utf-8").decode(buffer)
    }
    

    Some where in your app –

    let appData = {...}
    
    async function onSave(event) {
      await write(new File(
        [serialize(appData)],
        `data-${Date.now()}.txt`
      ))
    }
    
    async function onLoad(event) {
      appData = deserialize(await read(pathToSaveFile))
    }
    

    Now your appData can be anything that can be represented with JSON.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search