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 -

const fetchJson = (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 -

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

Creating the userRegister function is easy too -

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

And finally userDelete -

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

Now we can put it all together

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

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 -

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

const test = () =>
  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 -

async function test()
{ const user = await userRegister({
    firstName: 'nick',
    lastName: 'smith',
    phone: '01980635243',
    email: 'nick@hotmail.com',
    password: '1234567891011',
    confirmPassword:'1234567891011'
  })

  const list1 = await userList()

  const delete = await userDelete("nick@hotmail.com")

  const list2 = await userList()

  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"