-
-
Save rayshih/dd950ddc7085033718a1b6cb165614da to your computer and use it in GitHub Desktop.
A comparison of promises and signals
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ----- start of "extracted functions" ------ | |
const toggleLoggedActivity = (data) => { | |
const selectedActivity = getActivity(activities, data.activityKey); | |
const selectedActivitySubCategory = getSubCategory(activities, data.activityKey); | |
const transactionCallback = toggleLoggedActivity(data, activities, selectedActivity, selectedActivitySubCategory); | |
const loggedProfileRef = firebase.database() | |
.ref(`loggedActivities/${data.datetime}/${data.profileUid}`); | |
return utils.getValue(loggedProfileRef) | |
.then((value) => { | |
const existingActivities = value.activities || {}; | |
return Promise.resolve(loggedProfileRef.transaction(transactionCallback)) | |
.then((result) => { | |
const updatedActivities = result.committed ? result.snapshot.val().activities : {}; | |
const tobeModifiedValues = result.committed | |
? calculatePointsCo2Modified(data, existingActivities, updatedActivities, activities, selectedActivity) | |
: null | |
const loggedActivitiesDetails = tobeModifiedValues ? tobeModifiedValues.loggedActivitiesPointsCo2 : []; | |
const pointsToBeModified = tobeModifiedValues ? tobeModifiedValues.toBeModifiedPoints : 0; | |
const co2ToBeModified = tobeModifiedValues ? tobeModifiedValues.tobeModifiedCo2 : 0; | |
if (result.committed === true) { | |
if (Object.keys(updatedActivities).length === 0) { | |
loggedProfileRef.remove(); | |
} | |
} | |
return { | |
pointsToBeModified, | |
co2ToBeModified, | |
updatedActivities, | |
activeChallengesKeys | |
} | |
}) | |
}) | |
} | |
const outputPointsAndCo2Modifiers = (pointsToBeModified, co2ToBeModified) => { | |
const profileCo2PointsRef = firebase.database().ref(`profiles/${data.profileUid}`); | |
const profileTransactionCallback = | |
updateProfileCo2Points(pointsToBeModified, co2ToBeModified); | |
return Promise.resolve(profileCo2PointsRef.transaction(profileTransactionCallback)); | |
} | |
const updateProfile = (existingActivities, updatedActivities, data) => { | |
const profileActivityCountRef = firebase.database().ref(`profiles/${data.profileUid}/activitiesCount`); | |
const profileTransactionCallback = | |
updateProfileActivityCount(data, existingActivities, updatedActivities); | |
return Promise.resolve(profileActivityCountRef.transaction(profileTransactionCallback)); | |
} | |
const getProfileChallenges = (data) => { | |
const profileChallengesRef = firebase.database() | |
.ref(`profileChallenges/${data.profileUid}`); | |
return utils.getValue(profileChallengesRef.orderByChild('challengeEndDatetime') | |
.startAt(Date.now())); | |
} | |
const updateChallengesPointsAndCo2 = (value, data) => { | |
const activeChallengesKeys = value | |
? Object.keys(value).filter((challengeKey) => { | |
return !Boolean(value[challengeKey].leftDatetime); | |
}) | |
: []; | |
const challengesPointsTransactions = activeChallengesKeys.map((activeChallengeKey) => { | |
const challengesPointsRef = firebase.database() | |
.ref(`challengesPoints/${activeChallengeKey}/${data.datetime}`); | |
const challengesPointsTransactionCallback = | |
updateChallengesPoints(data, pointsToBeModified, co2ToBeModified, loggedActivitiesDetails); | |
return challengesPointsRef.transaction(challengesPointsTransactionCallback); | |
}); | |
return Promise.all(challengesPointsTransactions); | |
} | |
const updateChallengesAveragePoints = (activeChallengesKeys, data) => { | |
const challengesAveragePointsTransactions = activeChallengesKeys.map((activeChallengeKey) => { | |
const challengesAveragePointsRef = firebase.database() | |
.ref(`challengesAveragePoints/${activeChallengeKey}/${data.datetime}`); | |
const challengesAveragePointsTransactionCallback = | |
updateChallengesAveragePoints(data, pointsToBeModified, loggedActivitiesDetails); | |
return challengesAveragePointsRef.transaction(challengesAveragePointsTransactionCallback); | |
}); | |
return Promise.all(challengesAveragePointsTransactions); | |
} | |
const updateChallengesLeaderboardPart1 = (activeChallengesKeys, data) => { | |
const challengesLeaderboardDataTransactions = activeChallengesKeys.map((activeChallengeKey) => { | |
const challengesLeaderboardDataRef = firebase.database() | |
.ref(`challengesLeaderboard/${activeChallengeKey}/${data.profileUid}`); | |
const challengesLeaderboardDataTransactionCallback = | |
updateLeaderboardData(data, pointsToBeModified, co2ToBeModified, loggedActivitiesDetails); | |
return challengesLeaderboardDataRef.transaction(challengesLeaderboardDataTransactionCallback); | |
}); | |
return Promise.all(challengesLeaderboardDataTransactions); | |
} | |
const updateChallengesLeaderboardPart2 = (activeChallengesKeys) => { | |
const challengesLeaderboardPositionTransaction = activeChallengesKeys.map((activeChallengeKey) => { | |
const challengesLeaderboardPositionRef = firebase.database() | |
.ref(`challengesLeaderboard/${activeChallengeKey}`); | |
const challengesLeaderboardsDataTransactionCallback = updateLeaderboardPosition(); | |
return challengesLeaderboardPositionRef.transaction(challengesLeaderboardsDataTransactionCallback); | |
}); | |
return Promise.all(challengesLeaderboardPositionTransaction); | |
} | |
const updateChallengesLeaderboard = (activeChallengesKeys, data) => { | |
return updateChallengesLeaderboardPart1(activeChallengesKeys, data) | |
.then(() => updateChallengesLeaderboardPart2(activeChallengesKeys)) | |
} | |
// ----- end of "extracted functions" ------ | |
module.exports = (data, progress, resolve, reject) => { | |
return toggleLoggedActivity({data}) | |
.then(({pointsToBeModified, co2ToBeModified, updatedActivities, existingActivities, activeChallengesKeys}) => { | |
return outputPointsAndCo2Modifiers(context) | |
.then(() => updateProfile(existingActivities, updatedActivities, data)) | |
.then(() => getProfileChallenges(data)) | |
.then((value) => updateChallengesPointsAndCo2(value, data)) | |
.then(() => updateChallengesAveragePoints(activeChallengesKeys, data)) | |
.then(() => updateChallengesLeaderboard(activeChallengesKeys, data)) | |
}) | |
.then(resolve) | |
.catch(reject); | |
}; | |
/* | |
* you could further hide these arguments without shared state | |
* by transform every function from | |
* | |
* const f = (a) => { | |
* return asyncRequest(a) | |
* } | |
* | |
* to | |
* | |
* const f = (context) => { | |
* return asyncRequest(context.a).then((b) => { | |
* return { | |
* ...context, | |
* b, | |
* } | |
* }) | |
* } | |
* | |
* then the code would become | |
*/ | |
module.exports = (data, progress, resolve, reject) => { | |
return toggleLoggedActivity(data) | |
.then(outputPointsAndCo2Modifiers) | |
.then(updateProfile) | |
.then(getProfileChallenges) | |
.then(updateChallengesPointsAndCo2) | |
.then(updateChallengesAveragePoints) | |
.then(updateChallengesLeaderboard) | |
.then(resolve) | |
.catch(reject); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This is a fair comparison because we do not need shared state in the function scope like above, | |
the signal itself has state that can be shared | |
*/ | |
module.exports = [ | |
outputSelectedActivity, | |
outputSelectedActivitySubCategory, | |
...getProfileLoggedActivitiesForSpecifiedDay([ | |
...toggleLoggedActivity([ | |
outputPointsAndCo2Modifiers, | |
...updateProfile([ | |
...getProfileChallenges([ | |
outputActiveChallenges, | |
...updateChallengesPointsAndCo2([ | |
[ | |
...updateChallengesAveragePoints, | |
...updateChallengesLeaderboard | |
], | |
resolveTask | |
]) | |
]) | |
]) | |
]) | |
]) | |
]; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment