Search code examples
javascriptnode.jsreactjses6-promise

Customize rejected response in Promise.all()


Hi I am trying to customize the error response if a promise from array fails

I have referred to Handling errors in Promise.all and developed the below code I might need to tweak it to get desired response. Need some help

I have following code implemented. Please run to see the out put

//User Data
const usersData = [{
    firstName: 'John',
    lastName: 'Smith',
    isResolved: true //I have this only to reject or resolve the promise
  },
  {
    firstName: 'Phil',
    lastName: 'Doe',
    isResolved: false
  },
  {
    firstName: 'Dan',
    lastName: 'Joe',
    isResolved: true
  }
]

//Promise which gets resolved
const delayResolveFunction = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const id = Math.floor((Math.random() * 10) + 1)
      resolve({
        userid: id,
        isSuccess: true
      })
    }, 100)

  })
}

// Promise which gets rejected
const delayRejectFunction = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const id = Math.floor((Math.random() * 10) + 1)
      reject({
        isSuccess: false
      })
    }, 100)

  })
}

//function which creates users based on whethere userid is present
const createUsers = (users) => {
  const promiseArray = [];
  users.forEach((user) => {
    let userId = user.id;

    if (!userId) {
      if (user.isResolved) {
        promiseArray.push(delayResolveFunction().then((response) => {
          userId = response.userid
          isSuccess = response.isSuccess
          return { ...user,
            userId,
            isSuccess
          }
        }))
      }
      if (!user.isResolved) {
        // statement is not executed because error is thrown
        promiseArray.push(delayRejectFunction().then((response) => {
          userId = response.userId
          return { ...user,
            userId
          }
        }))
      }

    } else return null;



  });
  // I have this logic to access the data even if one promise fails among three
  //If you look at the response object we can see request for second user failed


  // My question is can I also send user object for failed response?
  return Promise.all(promiseArray.map(p => p.catch((err) => {
    return err;
  })))
}


//mainfunction where array of promises are resolved
const mainFunction = async() => {
  try {
    const arrayOfPromises = await createUsers(usersData);
    console.log(arrayOfPromises)
  } catch (err) {
    console.log(err)
  }
}

mainFunction();

I am looking to get output as below

[{
    "firstName": "John",
    "lastName": "Smith",
    "isResolved": true,
    "userId": 3,
    "isSuccess": true
  },
  {
    //for failed response
    "firstName": 'Phil',
    "lastName": 'Doe',
    "isResolved": false,
    "isSuccess": false
  },
  {
    "firstName": "Dan",
    "lastName": "Joe",
    "isResolved": true,
    "userId": 8,
    "isSuccess": true
  }
]

if you like to have a look in codepen here is the link https://codepen.io/punith77/pen/OBdLZa?editors=0012

Please let me know if I can get output as above


Solution

  • Use a catch instead of then after the delayRejectFunction call. And use the error object in the catch to get the isSuccess. I have posted the changes below.

    //User Data
    const usersData = [{
        firstName: 'John',
        lastName: 'Smith',
        isResolved: true //I have this only to reject or resolve the promise
      },
      {
        firstName: 'Phil',
        lastName: 'Doe',
        isResolved: false
      },
      {
        firstName: 'Dan',
        lastName: 'Joe',
        isResolved: true
      }
    ]
    
    //Promise which gets resolved
    const delayResolveFunction = () => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          const id = Math.floor((Math.random() * 10) + 1)
          resolve({
            userid: id,
            isSuccess: true
          })
        }, 100)
    
      })
    }
    
    // Promise which gets rejected
    const delayRejectFunction = () => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          reject({
            isSuccess: false
          })
        }, 100)
    
      })
    }
    
    //function which creates users based on whethere userid is present
    const createUsers = (users) => {
      const promiseArray = [];
      users.forEach((user) => {
        let userId = user.id;
    
        if (!userId) {
          if (user.isResolved) {
            promiseArray.push(delayResolveFunction().then((response) => {
              userId = response.userid
              isSuccess = response.isSuccess
              return { ...user,
                userId,
                isSuccess
              }
            }))
          }
          if (!user.isResolved) {
            // statement is not executed because error is thrown
            promiseArray.push(delayRejectFunction().catch((errorObj) => {
              var isSuccess = errorObj.isSuccess;
              return { ...user,
                isSuccess
              }
            }))
          }
    
        } else return null;
    
    
    
      });
      // I have this logic to access the data even if one promise fails among three
      //If you look at the response object we can see request for second user failed
    
    
      // My question is can I also send user object for failed response?
      return Promise.all(promiseArray.map(p => p.catch((err) => {
        return err;
      })))
    }
    
    
    //mainfunction where array of promises are resolved
    const mainFunction = async() => {
      try {
        const arrayOfPromises = await createUsers(usersData);
        console.log(arrayOfPromises)
      } catch (err) {
        console.log(err)
      }
    }
    
    mainFunction();

    Hope this helps :)