React.js, print something after all getDownloadURL functions completes - javascript

i am trying to get all the URL from Firebase.I need to print something after all the getDownloadURL completes. I have tried to add .then(function()){}after the storageRef.listAll(), however it does not work. Can someone help me? Thank you so much!
getAllURL = product => {
// Get all the images from the firebase
var storage = firebase.storage();
var that = this;
const storageRef = storage.ref(`image/${product}`)
storageRef.listAll().then(function(result) {
result.items.forEach(function(imageRef) {
imageRef.getDownloadURL().then(function(url) {
let a = 'a'
that.state.temp3.push(a)
console.log("789")
}).catch(function(error) {});
console.log("123")
})
console.log("456")
})
}

I declared a variable called promises and assigned all of the promises to it. After that, I used Promise.all to wait for all of the promises to resolve.
getAllURL = product => {
// Get all the images from the firebase
var storage = firebase.storage();
var that = this;
const storageRef = storage.ref(`image/${product}`);
storageRef.listAll().then(function(result) {
const promises = result.items.map(function(imageRef) {
return imageRef
.getDownloadURL()
.then(function(url) {
let a = "a";
that.state.temp3.push(a);
console.log("789");
})
.catch(function(error) {});
});
Promise.all(promises)
.then((results) => console.log('Promises resolved', results))
});
};

Related

How do I refactor this Cypress fixtures code?

I need help refactoring this Cypress code
let stripe;
let bookService;
let images;
let moreDetails;
let checkoutDetails;
let wait;
before(() => {
cy.visit('/');
cy.fixture('stripe').then((data) => {
stripe = data;
});
cy.fixture('bookService').then((data) => {
bookService = data;
});
cy.fixture('images').then((data) => {
images = data;
});
cy.fixture('moreDetails').then((data) => {
moreDetails = data;
});
cy.fixture('wait').then((data) => {
wait = data;
});
});
I have tried
stripe = cy.fixture('stripe')
but it's returning an object { specWindow: ..., chainerId: ...}
It's ok to import fixtures at the to of the spec. You can use require() to refactor the fixtures in the way you suggest,
let stripe = require('./cypress/fixtures/stripe.json')
let bookService = require('./cypress/fixtures/bookService.json')
let images = require('./cypress/fixtures/images.json')
let moreDetails = require('./cypress/fixtures/moreDetails.json')
let wait = require('./cypress/fixtures/wait.json')
before(() => {
cy.visit('/');
});

How to get PromiseValue with PromiseĀ {<pending>} Firebase?

Good afternoon. I'm new to working with Firebase batabase. Please tell me how to get data from my database to work with them farther.
Now my function returns Promise {} with the date that I need inside PromiseValue. How do I get it right.
Now my code looks like this
let firebaseConfig = {
....
};
firebase.initializeApp(firebaseConfig);
let ref = firebase.database().ref('/data')
function getDataPromise() {
return ref.once('value').then(function(snapshot) {
return snapshot.val();
});
}
let res = getDataPromise()
console.log(res)
I will be glad to any answer
You have to use then() to get the data,like below
let firebaseConfig = {
....
};
firebase.initializeApp(firebaseConfig);
let ref = firebase.database().ref('/data')
function getDataPromise() {
return ref.once('value').then(function(snapshot) {
return snapshot.val();
});
}
let res = getDataPromise()
// Use then() with a callback to get data
res.then(data => {
console.log(data)
})
console.log(res)

Firebase data in combination with async promises with javascript

I have a function declared that gets Firebase data async. The function have to wait until all the data is put inside an object. For some reason the function continues without waiting until the object has been set.
/** Get the data content */
const getData = async (widget, userId) => {
let promises = [];
let mainObject = {};
const pivotData = {};
const pivotName =
'user' + widget[1].type.charAt(0).toUpperCase() + widget[1].type.slice(1);
//Object entries
mainObject = {
default: widget[1],
};
mainObject['widgetId'] = widget[0];
//Main listner
const mainRef = firebase
.database()
.ref()
.child(widget[1].type);
//Pivot Listner
const pivotRef = firebase
.database()
.ref()
.child(pivotName)
.child(userId);
//Set promise
promises.push(
new Promise(async resolve => {
pivotRef
.once('value', snapPivot => {
snapPivot.forEach(function(result) {
if (result.val().widgetId === widget[0]) {
pivotData[result.key] = result.val();
mainObject['pivot'] = pivotData;
mainObject['typeId'] = result.key;
mainObject['main'] = {};
console.log('1');
mainRef.child(result.key).once('value', snapshot => {
console.log('2');
mainObject['main'][result.key] = snapshot.val();
});
}
});
})
.then(() => {
resolve();
console.log('3');
});
})
);
Promise.all(promises).then(results => {
return mainObject;
});
};
The expected outcome of the console.logs is 1,2,3 but it is showing 1,1,3,2
Why is the function not waiting on the .once function inside the loop?
The issue is that you are not waiting for the promises from mainRef.child(result.key).once() to resolve.
Additionally you are only pushing one promise to your promises array you want to be pushing the promise you get when calling mainRef.child(result.key).once().
Use await Promise.all() see MDN.
// Reference.once returns a promise Promise<DataSnapshot>
const dataSnapshot = await pivotRef.once('value');
let promises = [];
dataSnapshot.forEach((result) => {
const key = result.key;
const data = result.val();
if (data.widgetId === widget[0]) {
pivotData[key] = data;
mainObject['pivot'] = pivotData;
mainObject['typeId'] = key;
mainObject['main'] = {};
console.log('1');
const promise = mainRef.child(result.key)
.once('value', snapshot => {
console.log('2');
mainObject['main'][result.key] = snapshot.val();
});
// add promise to our promises array
promises.push(promise);
}
});
// wait for all the promises to be fulfilled (i.e resolved)
await Promise.all(promises);
// assuming 3 only needs to be logged once (at the end)
console.log('3');
console.log(mainObject);
return mainObject;
Let me know if this works!

Using promises in Axios requests

I am trying to work out the best way to achieve something. When I land on a Profile page, the Profile component loads the data for that profile. This is assigned to this.profile. Within this data is a path to a file, where I want to process some data using this file. To me, the below approach seems slightly risky.
created() {
let vm = this;
let url = `/api/profile/${this.$route.params.id}`;
axios.get(url).then(response => {
this.profile = response.data;
d3.json(response.data.fileName)
.then(function (data) {
//do some stuff
}).catch(function (error) {
// handle error
});
});
}
Instead of that, I want to ensure that I first have the data from the axios call. So I am thinking I need a promise? I was thinking something more along the lines off
created() {
let vm = this;
let url = `/api/profile/${this.$route.params.id}`;
axios.get(url).then(response => {
this.profile = response.data;
}).then() {
d3.json(response.data.fileName)
.then(function (data) {
//do some stuff
}).catch(function (error) {
// handle error
});
};
}
But the above is incorrect, it is mainly to show what I am trying to achieve. I was wondering how I can maybe use deferred and promises to only execute the d3 stuff once the axios call is made.
Thanks
You can solve this by chaining promises, assuming that d3.json returns a promise:
created() {
let vm = this;
let url = `/api/profile/${this.$route.params.id}`;
axios.get(url)
.then(response => {
this.profile = response.data
return d3.json(response.data.fileName)
}).then(data => {
//do some stuff
}).catch(err => {
//log error
})
}
That's where async/await comes in handy. A you don't need to save this to a variable and B you have cleaner, more readable code.
async created() {
const url = `/api/profile/${this.$route.params.id}`;
const { data } = await axios.get(url); // Optional destructuring for less clutter
this.profile = data;
const d3Data = await d3.json(data.fileName);
//do whatever you want
}
async created() {
let vm = this;
let url = `/api/profile/${this.$route.params.id}`;
try {
const {data} = await axios.get(url)
const d3Data = await d3.json(data.fileName)
} catch(err) {
//error
}
}

Execute code after fs.writeFile using async/await

I have a function, startSurvey, which, when run, checks if there are questions in a .json file. If there are no questions, it fetches some questions from Typeform and writes them to the .json file using saveForm. After it writes, I would like to continue executing some code that reads the .json file and logs its contents. Right now, await saveForm() never resolves.
I have promisified the fs.readFile and fs.writeFile functions.
//typeform-getter.js
const fs = require('fs')
const util = require('util')
const fetch = require('cross-fetch')
require('dotenv').config()
const conf = require('../../private/conf.json')
const typeformToken = conf.tokens.typeform
const writeFile = util.promisify(fs.writeFile)
const getForm = async () => {
const form = await fetch(`https://api.typeform.com/forms/${process.env.FORM_ID}`, {
headers: {
"Authorization": `bearer ${typeformToken}`
}
}).then(res => res.json())
const fields = form.fields
return fields
}
const saveForm = async () => {
const form = await getForm()
return writeFile(__dirname + '/../data/questions.json', JSON.stringify(form))
.then((e) => {
if (e) console.error(e)
else console.log('questions saved')
return
})
}
module.exports = saveForm
//controller.js
const fs = require('fs')
const util = require('util')
const request = require('request')
require('dotenv').config()
const typeformGetter = require('./functions/typeform-getter')
const readFile = util.promisify(fs.readFile)
const saveForm = util.promisify(typeformGetter)
let counter = 1
const data = []
const getQuestions = async() => {
console.log('called')
try {
let data = await readFile(__dirname + '/data/questions.json')
data = JSON.parse(data)
return data
} catch (e) {
console.error('error getting questions from read file', e)
}
}
const startSurvey = async (ctx) => {
try {
const questions = await getQuestions()
if (!questions) await saveForm()
console.log(questions) //NEVER LOGS
} catch (error) {
console.error('error: ', error)
}
}
startSurvey() //function called
I don't know your exact error, but there are multiple things wrong with your code:
You're using incorrectly the promisified version of fs.writeFile, if an error occurs, the promise will be rejected, you won't get a resolved promise with an error as the resolved value, which is what you're doing.
Use path.join instead of concatenating paths.
In startSurvey, you're using console.log(questions) but that wont have any data if questions.json doesn't exists, which should happen the first time you run the program, since it's filled by saveForm, so you probably want to return the questions in saveForm
So saveForm should look something like this:
const saveForm = async () => {
const form = await getForm();
const filePath = path.join(path.__dirname, '..', 'data', 'questions.json');
await writeFile(filePath, JSON.stringify(form));
console.log('questions saved');
return form;
}
And startSurvey
const startSurvey = async (ctx) => {
try {
const questions = await getQuestions() || await saveForm();
// This will be logged, unless saveForm rejects
// In your code getQuestions always resolves
console.log(questions);
} catch (error) {
console.error('error: ', error)
}
}
In your controller.js you're using util.promisify on saveForm when it is already a promise.
So it should be:
const saveForm = require('./functions/typeform-getter')

Categories