NevD
NevD

Reputation: 315

Chaining promises including fetch

I have a React form with a file as an input, and the onFileChange saves setFile(e.target.files[0]) (and also toggle a boolean change). Then when I submit the form:

I thought that chaining promises should do the job, but I can't achieve it.

Inside my onFormSubmit, I first define a promise that captures the none async data:

function init(fd){
  fd.append('input1'...)
  return Promise.resolve(fd)
}

so I can reuse the formdata to feed the next promise upLoadToCL that should 'normally' asynchronously append the response object from the cloud to the formdata, with:

init(new FormData).then(res => upLoadToCL(res)).then(res=> ...)

function upLoadToCL(fd) {
      if (changed) {
        // send 'file' (saved as state variable after input) to the cloud
        const newfd = new FormData();
        newfd.append("file", file);
        newfd.append("upload_preset", "ml_default");
        fetch(`https://api.cloudinary.com/v1_1/${cloudName}/upload`, {
          method: "POST",
          body: newfd,
        })
          .then((res) => res.json())
          // append the formdata argument 'fd' with the result
          .then((res) => {
            setPhoto(res);
            fd.append("event[directCLUrl]", res.url);
            fd.append("event[publicID]", res.public_id);
          })
          .catch((err) => {
            throw new Error(err);
          });
        return Promise.resolve(fd);
      }
    }

I checked that the first promise works and sends to the second promise a 'prefilled' formdata. Then the post request works, and returns a response as I can see that the state variable photo is updated some time in the futur. However, the promise itself returns a void formdata, even without chaining:

upLoadToCL(new FormData())
  .then(res=> {
    for (let [k,v] of res){
      console.log(k,v)
    }
  })

returns nothing.

Upvotes: 1

Views: 92

Answers (1)

Bergi
Bergi

Reputation: 665380

You're already doing the promise chaining fine. You just need to return the result of that promise chain instead of the Promise.resolve(fd) from your function:

function upLoadToCL(fd) {
  if (changed) {
    // send 'file' (saved as state variable after input) to the cloud
    const newfd = new FormData();
    newfd.append("file", file);
    newfd.append("upload_preset", "ml_default");
    return fetch(`https://api.cloudinary.com/v1_1/${cloudName}/upload`, {
//  ^^^^^^
      method: "POST",
      body: newfd,
    })
    .then((res) => res.json())
    .then((res) => {
      setPhoto(res);
      // append the formdata argument 'fd' with the result
      fd.append("event[directCLUrl]", res.url);
      fd.append("event[publicID]", res.public_id);
      return fd;
//    ^^^^^^ fulfilling the promise with the updated fd
    });
  } else {
    return Promise.resolve(fd);
//  ^^^^^^ always returning a promise for fd from uploadToCL()
  }
}

Upvotes: 2

Related Questions