Skip to content Skip to sidebar Skip to footer

Problem With Fetch Calls And Promise Chaining

**edit: was a problem on the backend So I've been having a problem with chaining promises. I ditched axios and async await to go back to re-learn the basics, as I must be making a

Solution 1:

Good for you to take a step back and really focus on learning the basics. You should know that fetch is a low-level interface and it's a rookie move to use it as-is. Programming is all about making your life easier. If you need to deal with JSON, let's write a fetchJSON specialization -

constfetchJson = (url, opts = {}) =>
  fetch(url, { ...opts, headers: 'Content-Type': 'application/json' })
    .then(r => r.json())

Even with our helper, we shouldn't jump to use it directly. By defining reusable functions, our code becomes more descriptive and easier to use -

constuserList = () =>
  fetchJson(`http://localhost:8080/users/all`)

Creating the userRegister function is easy too -

constuserRegister = (user = {}) =>
  fetchJson
    ( `http://localhost:8080/users/register`
    , { method: "POST", mode: "cors", body: JSON.stringify(user) }
    )

And finally userDelete -

constuserDelete = email =>
  fetchJson
    ( `http://localhost:8080/users/delete-email/${email}`
    , { method: "DELETE", mode: "cors" }
    )

Now we can put it all together

consttest = () =>
  userRegister({
    firstName: 'nick',
    lastName: 'smith',
    phone: '01980635243',
    email: 'nick@hotmail.com',
    password: '1234567891011',
    confirmPassword:'1234567891011'
  })
  .then(user => {
    console.log("registered", user)
    returnuserList()
  })
  .then(users => {
    console.log("list", users)
    returnuserDelete("nick@hotmail.com")
  })
  .then(_ =>console.log("user deleted")
    returnuserList()
  })

Notice we don't attach any .catch to the test. This is left for the caller to decide. We could run the test like this -

test().then(console.log, console.error)

don't stop there

Do you see the pattern of .then(something => { console.log(something), ... }). We could make a generic log function that makes this intention more clear -

constlog = label => data =>
{ console.log(label, data)
  return data
}

consttest = () =>
  userRegister({
    firstName: 'nick',
    lastName: 'smith',
    phone: '01980635243',
    email: 'nick@hotmail.com',
    password: '1234567891011',
    confirmPassword:'1234567891011'
  })
  .then(log("registered"))
  .then(_ =>userList())
  .then(log("list"))
  .then(_ =>userDelete("nick@hotmail.com"))
  .then(log("user deleted"))
  .then(_ =>userList())

But there's a bad practice here. console.log is a side effect and it would be nice if we could get the result of each promise back from the test. We can plainly see that _ => ... is replacing the value of the previous promise in the chain and only the final promise value will be available to the caller.

You could append all the results to an array and thread the array through to each successive promise, but this is also rather tedious. This is particularly where async and await are helpful as they make promise values available in the same scope -

asyncfunctiontest()
{ const user = awaituserRegister({
    firstName: 'nick',
    lastName: 'smith',
    phone: '01980635243',
    email: 'nick@hotmail.com',
    password: '1234567891011',
    confirmPassword:'1234567891011'
  })

  const list1 = awaituserList()

  constdelete = awaituserDelete("nick@hotmail.com")

  const list2 = awaituserList()

  return [user, list1, deleted, list2] // <- all results
}

Now console.log has been disentangled from test and the result of all promise values is available to the caller

test().then(console.log, console.error)

Post a Comment for "Problem With Fetch Calls And Promise Chaining"