Skip to content

Instantly share code, notes, and snippets.

@rayshih
Forked from christianalfoni/promises.js
Last active September 5, 2016 07:57
Show Gist options
  • Save rayshih/dd950ddc7085033718a1b6cb165614da to your computer and use it in GitHub Desktop.
Save rayshih/dd950ddc7085033718a1b6cb165614da to your computer and use it in GitHub Desktop.
A comparison of promises and signals
// ----- 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 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