Skip to content

Instantly share code, notes, and snippets.

@christianalfoni
Created August 17, 2016 14:05
Show Gist options
  • Save christianalfoni/900a739b3a62b63e9bd030c2edbfc8b1 to your computer and use it in GitHub Desktop.
Save christianalfoni/900a739b3a62b63e9bd030c2edbfc8b1 to your computer and use it in GitHub Desktop.
A comparison of promises and signals
module.exports = (data, progress, resolve, reject) => {
const loggedProfileRef = firebase.database()
.ref(`loggedActivities/${data.datetime}/${data.profileUid}`);
const profileChallengesRef = firebase.database()
.ref(`profileChallenges/${data.profileUid}`);
const selectedActivity = getActivity(activities, data.activityKey);
const selectedActivitySubCategory = getSubCategory(activities, data.activityKey);
const transactionCallback = toggleLoggedActivity(data, activities, selectedActivity, selectedActivitySubCategory);
let existingActivities = {};
let updatedActivities = {};
let loggedActivitiesDetails = [];
let activeChallengesKeys = [];
let pointsToBeModified = 0;
let co2ToBeModified = 0;
utils.getValue(loggedProfileRef)
.then((value) => {
if (value !== null) {
existingActivities = value.activities;
}
})
.then(() => {
return loggedProfileRef.transaction(transactionCallback);
})
.then((result) => {
if (result.committed === true) {
updatedActivities = result.snapshot.val().activities || {};
if (Object.keys(updatedActivities).length === 0) {
loggedProfileRef.remove();
}
const tobeModifiedValues = calculatePointsCo2Modified(data, existingActivities, updatedActivities, activities, selectedActivity);
co2ToBeModified = tobeModifiedValues.tobeModifiedCo2;
pointsToBeModified = tobeModifiedValues.toBeModifiedPoints;
loggedActivitiesDetails = tobeModifiedValues.loggedActivitiesPointsCo2;
}
})
.then(() => {
const profileCo2PointsRef = firebase.database().ref(`profiles/${data.profileUid}`);
const profileTransactionCallback =
updateProfileCo2Points(pointsToBeModified, co2ToBeModified);
return profileCo2PointsRef.transaction(profileTransactionCallback);
})
.then(() => {
const profileActivityCountRef = firebase.database().ref(`profiles/${data.profileUid}/activitiesCount`);
const profileTransactionCallback =
updateProfileActivityCount(data, existingActivities, updatedActivities);
return profileActivityCountRef.transaction(profileTransactionCallback);
})
.then(() => {
return utils.getValue(profileChallengesRef.orderByChild('challengeEndDatetime')
.startAt(Date.now()));
})
.then((value) => {
if (value) {
activeChallengesKeys = Object.keys(value).filter((challengeKey) => {
return !Boolean(value[challengeKey].leftDatetime);
});
}
})
.then(() => {
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);
})
.then(() => {
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);
})
.then(() => {
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);
})
.then(() => {
const challengesLeaderboardPositionTransaction = activeChallengesKeys.map((activeChallengeKey) => {
const challengesLeaderboardPositionRef = firebase.database()
.ref(`challengesLeaderboard/${activeChallengeKey}`);
const challengesLeaderboardsDataTransactionCallback = updateLeaderboardPosition();
return challengesLeaderboardPositionRef.transaction(challengesLeaderboardsDataTransactionCallback);
});
return Promise.all(challengesLeaderboardPositionTransaction);
})
.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
])
])
])
])
])
];
@benjaminmbrown
Copy link

Wow this is a striking difference. I'm very familiar with the pains of dealing with the verbosity of promises and promise chaining, so this has my attention now. Thank you for showing this. -Ben

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment