Get random element from json array

Get random element from json array
0

I have a new wall I’m against.

I thought I got how it worked for running thru an array and giving a random element. But the code gives me an error in console:

TypeError: Cannot read property 'length' of undefined
    at getRandomKanji (kanjitab.js:40)

This is the code I’m trying to recreate the commented part of the code but for my json array.

var myfetch = fetch("https://kanjialive-api.p.rapidapi.com/api/public/kanji/all", {
	"method": "GET",
	"headers": {
		"x-rapidapi-host": "",
		"x-rapidapi-key": ""
	}
})


var i, x = "";

/** Parse response object
 * returns object parsed from json
 */
const getJsonFromRes = (res) => res.json();


 
/**  Logs some data. 
 * returns undefined
 */
const logData = (data) => console.log(data[2].kanji.character);

/** Ignores its data parameter. Attempts to set an element to an uninitialized variable.
 */
//const accessKanji = (data) => {
//	let chars = data.map(el => el.kanji.character + "<br>").join("");
//	document.getElementById('kanji').innerHTML = chars;
//  }

console.log(x)
// print error to console. returns undefined.
const logError = (err) => console.log(err);

// Example comment for what I want to achieve
  //var myArray = ['January', 'February', 'March']; 
  //var rand = myArray[Math.floor(Math.random() * myArray.length)];
	//console.log(rand);
const getRandomKanji = (data) => {
	let charss = getRandomKanji([Math.floor(Math.random() * data.length)]);
	console.log(charss);
}

myfetch 
  .then(getJsonFromRes) 
  .then(logData) 
  .then(getRandomKanji)
  //.then(accessKanji) 
  .catch(logError);


There is a lot going on; but I’m assuming data is getting to the getRandomKanji function

let charss = data[Math.floor(Math.random() * data.length)]

Are you providing the API key when you make the request or have you deliberately redacted it in the code you posted? Because can’t currently test this.

But you aren’t returning the data in the functions, you’ve even commented to that effect:

/**  Logs some data. 
 * LOOK------>>>>> returns undefined
 */
const logData = (data) => console.log(data[2].kanji.character);

So when you go onto the next then in the chain, you’re passing it undefined instead of the data, and you can’t map over undefined. To be explicit:

fetch(something)
  .then(data => {
    /* The value of `data` should be some JSON that came back
     * from `fetch` */
    return data.json();
    /* The return value is the result of parsing that JSON string
     * to a JS object */
  })
  .then(data => {
    /* the value of `data` is the return value of the last function
     * So `data` here is the value you've got from JSON.parse-ing the
     * response from your `fetch` call.
     */
    return console.log(data);
    /* the return value is undefined! */
  })
  .then(data => {
    /* the value of `data` here is the return value of the last function,
     * which was `undefined`, so `data` is `undefined`
     */
 ...

I simply don’t get where the data is then? And your code ECMA 6 then? I’m sometimes confused between the old way and the new way when analyzing codes.

I Tried this because I thought I needed a function to get all the second characters and a new function to go random through the kanji.

var myfetch = fetch("https://kanjialive-api.p.rapidapi.com/api/public/kanji/all", {
	"method": "GET",
	"headers": {
		"x-rapidapi-host": "kanjialive-api.p.rapidapi.com",
		"x-rapidapi-key": "f1fbf27c32mshce2a5ab13e928c9p155a0cjsn3eb8cd7f90a2"
	}
})


var i, x = "";

/** Parse response object
 * returns object parsed from json
 */
const getJsonFromRes = (res) => res.json();


 
/**  Logs some data. 
 * returns undefined
 */
const logData = (data) => console.log(data[1].kanji.character);

/** Ignores its data parameter. Attempts to set an element to an uninitialized variable.
 */
//const accessKanji = (data) => {
//	let chars = data.map(el => el.kanji.character + "<br>").join("");
//	document.getElementById('kanji').innerHTML = chars;
//  }

const GetRandomKanji = (data) => {
	let chars = data.map(el => el.kanji.character + "<br>").join("");
	//[Math.random() * data.length | 2];
	console.log(chars);
}

console.log(x)
// print error to console. returns undefined.
const logError = (err) => console.log(err);

// Example comment for what I want to achieve
  //var myArray = ['January', 'February', 'March']; 
  //var rand = myArray[Math.floor(Math.random() * myArray.length)];
	//console.log(rand);


myfetch 
  .then(getJsonFromRes)
  .then(logData)
  .then(GetRandomKanji) 
  //.then(accessKanji) 
  .catch(logError);

console.log(getJsonFromRes);
console.log(logData);

It’s a chain of functions. Take this data then do something to it then pass it to the next function then do something to it then pass it this the next function etc etc. Whatever the return value of the previous function is, that’s the input for the next one. If you return undefined from the previous function, that’s the input to the next one in the chain.

If you want to get some specific data from a function, return that specific data

data is an array of object. Are you wanting to randomly select a certain number of the kanji characters (from the data set) or are you wanting to select all of the characters and randomly order them? If you can explain what you are ultimately trying to do with the data received back from the fetch, that would be great. Maybe, you are only trying to return a single random element.

I indeed want to return a single random element! But within the scope of the characters.
As my initial code returned all the kanji characters of the complete array. I want to random give only one of these with every refresh.

So I need to create the correct function that uses the former chain so the result isn’t undefined. Correct?
If so I thought that that was the case.

const logData = (data) => console.log(data[1].kanji.character);

My thought was I needed to put a variable ‘random’ instead of the [1] so it would be

const logData = (data) => console.log(data[random].kanji.character);

You have a few issues to resolve.

The correct order of the fetch thens is important. The first one is fine. The second one should be the one that gets the random kanji from the previous getJsonFromRes return value and the third one would log the value returned from the second.

The problem is that function that is supposed to return a random kanji is not written correctly and has a different spelling when called than the function name you defined to perform the task. Remember that the value passed to the 2nd then callback is just an array of objects. You want to randomly select an index of the array. Arrays are zero-indexed, so you can review Generate Random Whole Numbers with JavaScript for exactly how to do this. Once you have a random index, you can simply return the element of data (passed to the function) which has the index of this random index you created. There is no need to map through the array or anything else.

Finally, the 3rd then callback would be the one which you will console.log the kanji character from the returned value (an object) second then. Since this returned value is an object, so you must reference the applicable nested property (kanji) to display it to the console.

1 Like