Reputation: 121
i am trying to get every image download URL from Firebase. It seems that the first 'this' is different from the second one. If i want to let the second 'this' equals to the value of the first, what should i do? Thank you so much!
getAllURL = product => {
// Get all the images from the firebase
var storage = firebase.storage();
console.log(this) // first this
const storageRef = storage.ref(`image/${product}`)
storageRef.listAll().then(function(result) {
result.items.forEach(function(imageRef) {
imageRef.getDownloadURL().then(function(url) {
console.log(this) // second this is undefined
}).catch(function(error) {});
})
})
}
componentDidMount() {
axios.get('/user/product')
.then(res=>{
if(res.data.code==0) {
this.setState({data:res.data.data},function(){
for (var i = 0; i < this.state.data.length; i++){
this.getAllURL(this.state.data[i].productName)
}
})
}
})
}
Upvotes: 0
Views: 64
Reputation: 1766
this
is one the most confusing features in Javascript. I'd recommended you to look more into the topic.
As for a shortcut, there're many ways to take care of that.
First method: just assigned the first this into some variable first.
getAllURL = product => {
// Get all the images from the firebase
var storage = firebase.storage();
console.log(this) // first this
var firstThis = this; // some people prefered to assign "var that = this;", lol
const storageRef = storage.ref(`image/${product}`)
storageRef.listAll().then(function(result) {
result.items.forEach(function(imageRef) {
imageRef.getDownloadURL().then(function(url) {
console.log(firstThis); // use the new variable to refer to the firstThis
}).catch(function(error) {});
});
});
}
Second method: make use of bind
function in javascript (a bit more advanced, and much better received from a functional programming perspective)
getAllURL = product => {
// Get all the images from the firebase
var storage = firebase.storage();
console.log(this) // first this
const storageRef = storage.ref(`image/${product}`)
storageRef.listAll().then((function(result) {
result.items.forEach((function(imageRef) {
imageRef.getDownloadURL().then((function(url) {
console.log(this);
}).bind(this)).catch(function(error) {}); // yet another binding to propagate "this" inside
}).bind(this)); // another binding to force "this" on this yet another inline function to equal the first this (propagate it down)
}).bind(this)); // this binding will force "this" inside this inline function to equals the firstThis
}
Note: It might get less confusing if amount of inline functions is reduced
getAllURL = product => {
// Get all the images from the firebase
var storage = firebase.storage();
console.log(this) // first this
const storageRef = storage.ref(`image/${product}`)
storageRef.listAll().then(listAllCallback.bind(this));
}
function listAllCallback(result) {
for (var i = 0; i<result.items.length; i++) {
var imageRef = result.items[i];
imageRef.getDownloadURL()
.then(downloadUrlCallback.bind(this))
.catch(function(error) {});
}
}
function downloadUrlCallback(url) {
console.log(this); // second this
}
Upvotes: 1