G.Rose
G.Rose

Reputation: 714

Merging two different Fetch calls with data from Jsonplaceholder.com

I am trying to merge or basically perform an inner join on two datasets provided by https://jsonplaceholder.typicode.com/comments and https://jsonplaceholder.typicode.com/posts. The join would of course be using the PostId and id keys of both data sets respectively; however I am unsure of how to actually do this. I've added my codepen: https://codepen.io/gabedesigns/pen/qMGgxY?editors=1111 and I seem to be getting an error saying that I am missing '()' for my constructor. After figuring this out I will also need to search for posts with provided post ID and the comments corresponding the post. Perhaps I need nested for loops in order to make this work? I've tried to look up some other information on this and couldn't seem to find much. If there are any other resources I may have skipped over please don't be afraid to link it below. I saw a post on here already talking about "inner joins" with javascript instead of SQL, but this is where I ran into some problems. Here is some code:

function getResults() {

  const equijoin = (xs, ys, primary, foreign, sel) => {
   const ix = xs.reduce((ix, row) => ix.set(row[primary], row), new Map());
    return ys.map(row => sel(ix.get(row[foreign]), row));
  };

  const postData = fetch("https://jsonplaceholder.typicode.com/posts")
   .then(function(response) {
     return response.json();
  });

  const commentData = fetch("https://jsonplaceholder.typicode.com/comments")
   .then(function(response) {
    return response.json();
  });

  const result = equijoin(postData, commentData,"id", "postId", ({title, 
  body}, {name,body}) => ({title,body,name}));

}

Upvotes: 1

Views: 1580

Answers (1)

D Lowther
D Lowther

Reputation: 1619

There were a couple of problems here. I think you may have been running afoul of the async nature of fetch in trying to pass a promise into your sort function rather than waiting for it to resolve, gathering them up into a Promise.all batch is one way to handle this. Also as noted by someone in the comments you are using destructuring on two variables with the same name, the two easy solutions here are don't destructure or use an alias. Hope this helps

function getResults() {
const checkResult = res => res.ok ? res.json() : Promise.resolve({});
const joinMap = ({title, body:lbody}, {name,body:rbody}) => ({title,lbody, rbody,name});

const equiJoin = (xs, ys, primary, foreign, sel) => {
    const ix = xs.reduce(
      (ix, row) => ix.set(row[primary], row), new Map()
    );
    return ys.map(row => sel(ix.get(row[foreign]), row));
}
const posts = fetch("https://jsonplaceholder.typicode.com/posts")
  .then(checkResult);
  
const comments = fetch("https://jsonplaceholder.typicode.com/comments")
  .then(checkResult);

return Promise.all([posts, comments])
  .then(([postData, commentData]) => {
    const result = equiJoin(postData, commentData,"id", "postId", joinMap);
    console.log(result);
  })
  .catch(err => console.error(err));
}
button {
  background-color: white;
  color: black;
  border: 2px solid #555555;
  border-radius: 4px;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  margin: 4px 2px;
  cursor: pointer;
}

button:hover {
  background-color: #555555;
  color: white;
}

input {
  width: 20vw;
  height: 10vh;
  padding: 0.5%;
  border-radius: 4px;
  border: 1px solid black;
}

#results {
  position: absolute;
  border: 1px solid gray;
  height: 60vh;
  width: 60vw;
  left: 20vw;
  top: 10vw;
}
<input type="text" id="postIDinput" placeholder="Post ID" required="true"></input>
<button type="submit" onclick="getResults()">Submit</button>

<div id="results"></div>

Upvotes: 4

Related Questions