Skip to content

Instantly share code, notes, and snippets.

@christianchown
Created April 19, 2018 08:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save christianchown/4945bc02a6b57642868d52592f4b3e86 to your computer and use it in GitHub Desktop.
Save christianchown/4945bc02a6b57642868d52592f4b3e86 to your computer and use it in GitHub Desktop.
Push redux-like actions to Firebase, and retrieve responses
export const pushActionPromise = async (firebase, type, payload) => {
// get the key for the new action about to be created
const actionRef = firebase.database().ref('action');
const newKey = actionRef.push().key;
// push the action
const fullPayload = {
uid: firebase.auth().currentUser.uid,
type,
payload,
};
await actionRef.child(newKey).set(fullPayload);
// return the key so the user can listen for a response
return Promise.resolve(key);
}
export const getActionResponsePromise = async (firebase, key) => {
// read action_reponse for currentUser
const ref = `action_response/${firebase.auth().currentUser.uid}`;
const responseRef = firebase.database().ref(ref);
const currentResponse = await responseRef.once('value').then(val => val.val());
// if the response for my key is already there
// delete it from firebase and return it
if (currentResponse && currentResponse[key]) {
await responseRef.child(key).set(null);
return Promise.resolve(currentResponse[key]);
}
// as it's not yet been written, listen for the response.
// if it appears, delete it from firebase and return it
let onSet = null;
const gotValue = new Promise((resolve) => {
onSet = responseRef.on('child_added', async (response) => {
if (response && response.key === key) {
if (onSet) {
responseRef.off('child_added', onSet);
onSet = null;
}
await responseRef.child(key).set(null);
resolve(response.val());
}
});
});
// a 3 second time out promise
const timedOut = new Promise((resolve, reject) => {
setTimeout(() => {
if (onSet) {
responseRef.off('child_added', onSet);
onSet = null;
}
reject(new Error('timed out'));
}, 30000);
});
// set a promise race in motion to either
// (a) resolve with our action_response or
// (b) reject after 3 seconds
return Promise.race([gotValue, timedOut]);
}
/*
// Usage
const actionKey = await actions.pushActionPromise(firebase, 'DO_THING', payload);
try {
const response = await actions.getActionResponsePromise(firebase, actionKey);
if (response) {
if (response.error) {
setCallout('error', 'I got an error response');
} else {
setCallout('success', 'I got a good response');
}
}
} catch (error) {
setCallout('error', 'I did not get a valid response');
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment