简体   繁体   中英

Ensuring certain steps occur in promise chain or stopping chain early

I am trying to sync some database data with local data. Specifically, I want to 'load' a LinkTable from the database (the load function, itself, handles the merging of the data) and then, AFTER the load function I want to push the LinkTable to the database. When done, the desired outcome would be that the database and the local versions of the LinkTable would be identical. To complicate matters, the load function can reject in ways that are acceptable... and I need to continue down the promise chain if that is the case.

Lastly, after the syncing of the LinkTable... I need to do additional tasks that rely on said LinkTable.

I'm using react/redux but the question is more about promises.

The relevant (failing) code looks like this:

     dispatch(loadLinkTableFromDB(username))
            .then((successLoadLinkTableMsg) => {
                console.log('Successfully loaded link table: ', successLoadLinkTableMsg)
                return dispatch(pushLinkTableToDB(username))
            })
            .catch((rejectLoadLinkTableReason) => {
                console.log("Failed to load link table from DB: " + rejectLoadLinkTableReason);
                if (allReasonsAcceptableForOverwrite(rejectLoadLinkTableReason)) {  // some rejection reasons are accectable... so if failed reason is okay.... 
                    return dispatch(pushLinkTableToDB(username));
                } else {
                    // console.log("Rejecting: ", rejectLoadLinkTableReason);
                    return Promise.reject(rejectLoadLinkTableReason); 
                }
            })
            .catch((unacceptableRejectionReasons) => {
                console.log('unacceptableRejectionReasons :', unacceptableRejectionReasons);
            })
            .then(( *do more stuff that relies on the LinkTable *))

My issue is that a an unacceptable rejection in loading the LinkTable... AND a rejection of any kind in pushing the link table from the first catch end up being caught by the second catch. When it's an unacceptable rejection, I want the entire promise chain to end. When it's an acceptable rejection and then a subsequent rejection in the pushLinkTableToDB... I want the promise chain to continue.

You'll want to use .then(…, …) instead of .then(…).catch(…) to only handle rejections from loadLinkTableFromDB but not from pushLinkTableToDB :

dispatch(loadLinkTableFromDB(username))
.then(loadLinkTableResultMsg) => {
    console.log('Successfully loaded link table: ', loadLinkTableResultMsg)
    return dispatch(pushLinkTableToDB(username))
}, loadLinkTableErrorReason => {
    console.log('Failed to load link table from DB: ', loadLinkTableErrorReason);
    if (allReasonsAcceptableForOverwrite(loadLinkTableErrorReason)) {
        return dispatch(pushLinkTableToDB(username));
    } else {
        throw loadLinkTableErrorReason; 
    }
})
.then( /* do more stuff that relies on the LinkTable */ )
.catch(unacceptableRejectionReasons => {
    console.log('unacceptableRejectionReasons :', unacceptableRejectionReasons);
})

However, given you want to pushLinkTableToDB in both cases, you might want to move that down the chain and remove the duplication:

dispatch(loadLinkTableFromDB(username))
.then(loadLinkTableResultMsg) => {
    console.log('Successfully loaded link table: ', loadLinkTableResultMsg)
}, loadLinkTableErrorReason => {
    console.log('Failed to load link table from DB: ', loadLinkTableErrorReason);
    if (!allReasonsAcceptableForOverwrite(loadLinkTableErrorReason)) {
        throw loadLinkTableErrorReason; 
    }
})
.then(() => dispatch(pushLinkTableToDB(username)))
.then( /* do more stuff that relies on the LinkTable */ )
.catch(unacceptableRejectionReasons => {
    console.log('unacceptableRejectionReasons :', unacceptableRejectionReasons);
})

Without the log messages, you can use only catch as well - you just need to place it before the pushLinkTableToDB call:

dispatch(loadLinkTableFromDB(username))
.catch(loadLinkTableErrorReason => {
    if (!allReasonsAcceptableForOverwrite(loadLinkTableErrorReason)) {
        throw loadLinkTableErrorReason; 
    }
})
.then(() => dispatch(pushLinkTableToDB(username)))
.then( /* do more stuff that relies on the LinkTable */ )
.catch(unacceptableRejectionReasons => {
    console.log('unacceptableRejectionReasons :', unacceptableRejectionReasons);
})

If you control the loadLinkTableFromDB function, you might even want to consider moving the catch invocation inside that function, so that the returned promise only rejects with unacceptable errors, and fulfills with reasonable results otherwise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM