javascript - Firebase在添加/删除数据时,应用程序不止一次执行功能
问题描述
我的钱应用程序有问题。当我从我的应用程序(产品集合)中添加/删除数据时,我的应用程序会执行多个“sumPrices()”函数。例如:当我添加一个产品时,制作一次,添加另一个产品,制作两次,添加另一个产品制作三个等。这与删除数据的方式相同。
在我的代码中做错了什么?
Callback.push 推送数据做数组,我从 firebase 取消订阅事件。AddStatsUI 将 UI 添加到我的 DOM。
index.js:
// delete products
const handleTableClick = e => {
console.log(e); // mouseevent
if (e.target.tagName === 'BUTTON'){
const id = e.target.parentElement.parentElement.getAttribute('data-id');
db.collection('users')
.doc(user.uid)
.collection('products')
.doc(id)
.delete()
.then(() => {
// show message
updateMssg.innerText = `Product was deleted`;
updateMssg.classList.add('act');
setTimeout(() => {
updateMssg.innerText = '';
updateMssg.classList.remove('act');
}, 3000);
productUI.delete(id);
products.sumPrices(user.uid, callbacks).then(value => {
sumStats.addStatsUI('','');
const unsubscribe = db.collection('users').doc(user.uid).get().then(snapshot => {
sumStats.addStatsUI(value[0], snapshot.data().budget);
})
callbacks.push(unsubscribe);
});
})
}
}
table.addEventListener('click', handleTableClick);
callbacks.push(() => table.removeEventListener('click', handleTableClick))
//add new products to firebase
const handleExpenseFormSubmit = e => {
e.preventDefault();
const name = expenseForm.productName.value.trim();
const price = Number(expenseForm.price.value.trim());
console.log(`Product added: ${name}, ${price}`);
const user = firebase.auth().currentUser.uid;
products.addProduct(name, price, user)
.then(() => {
products.sumPrices(user, callbacks).then(value => {
sumStats.addStatsUI('','');
const unsubscribe = db.collection('users').doc(user).onSnapshot(snapshot => {
sumStats.addStatsUI(value, snapshot.data().budget);
})
callbacks.push(unsubscribe);
});
expenseForm.reset()
})
.catch(err => console.log(err));
}
expenseForm.addEventListener('submit', handleExpenseFormSubmit);
callbacks.push(() => expenseForm.removeEventListener('submit', handleExpenseFormSubmit))
产品.js:
class Product {
constructor(name, price, budget, user) {
this.products = db.collection('users');
this.budget = budget;
this.name = name;
this.price = price;
this.user = user;
}
async addProduct(name, price, user) { //dodaje produkt do firebase
const now = new Date();
const product = {
name: name,
price: price,
created_at: firebase.firestore.Timestamp.fromDate(now),
};
const response = await this.products.doc(user).collection('products').add(product);
return response;
}
getProducts(callback, user){ //download list from firebase
this.products.doc(user).collection('products')
.orderBy("created_at", "desc")
.onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
if(change.type === 'added'){
//udpate UI
return callback(change.doc.data(), change.doc.id);
}
});
});
}
updateBudget(budget, user){
this.budget = budget;
db.collection('users').doc(user).update({budget: budget});
// callbacks.push(unsubscribe);
}
async sumPrices(user, callbacks){
let finish = [];
const unsubscribe = this.products.doc(user).collection('products').onSnapshot(snapshot => {
let totalCount = 0;
snapshot.forEach(doc => {
totalCount += doc.data().price;
});
const a = totalCount;
console.log(a);
finish.push(a);
return finish;
})
callbacks.push(unsubscribe);
return finish;
};
};
sumStatsUI.js:
class Stats {
constructor(stats, circle, budget){
this.stats = stats;
this.circle = circle;
this.budget = budget;
}
addStatsUI(data, budget){
if(data) {
const outcome = Math.round(data * 100) / 100;
const sumAll = Math.round((budget - outcome) * 100) / 100;
this.stats.innerHTML += `
<div><span class="budget-name">Budget: </span> <span class="stat-value">${budget}$</span></div>
<div><span class="budget-name">Outcome: </span> <span class="stat-value outcome-value">${outcome}$</span></div>
<div><span class="budget-name">All: </span> <span class="stat-value last-value">${sumAll}$</span></div>
`;
const circle = Math.round(((outcome * 100) / budget) * 100) / 100;
this.circle.innerHTML += `${circle}%`;
} else {
this.stats.innerHTML = '';
this.circle.innerHTML = '';
}};
};
导出默认统计信息;
解决方案
好的,对我的代码进行了一些改进,但仍然存在订阅问题。现在一切正常,但是当我注销并登录函数 getProducts() 和 updateBudget() 时,没有取消订阅。
这里的代码:index.js:
//get the products and render
const unsubscribe = products.getProducts((data, id) => {
console.log(data, id);
productUI.render(data, id);
}, user.uid);
callbacks.push(unsubscribe);
//update budget + form
const handleBudgetFormSubmit = e => {
e.preventDefault();
//update budget
const budget = Number(budgetForm.budget_value.value.trim());
sumStats.addStatsUI('', '');
products.updateBudget(budget, user.uid);
//reset form
budgetForm.reset();
const budgetCart = document.querySelector('#budget');
budgetCart.classList.remove('active');
// show message
updateMssg.innerText = `Your budget was updated to ${budget}$`;
updateMssg.classList.add('act');
setTimeout(() => {
updateMssg.innerText = '';
updateMssg.classList.remove('act');
}, 3000);
};
budgetForm.addEventListener('submit', handleBudgetFormSubmit);
callbacks.push(() =>
budgetForm.removeEventListener('submit', handleBudgetFormSubmit)
);
否则 onAuthStateChanged() -> if(user):
} else {
console.log('user logged out');
authUI('');
productUI.render('');
sumStats.addStatsUI('');
console.log('Callbacks array', callbacks);
callbacks.forEach(callback => callback());
callbacks.length = 0;
} });
getProducts() 和 updateBudget():
getProducts(callback, user) {
//download list from firebase
this.products
.doc(user)
.collection('products')
.orderBy('created_at', 'desc')
.onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
if (change.type === 'added') {
//udpate UI
return callback(change.doc.data(), change.doc.id);
}
});
});
}
updateBudget(budget, user) {
console.log('budget', budget, user);
const db = firebase.firestore();
// this.budget = budget;
db.collection('users')
.doc(user)
.update({ budget: budget });
}
当我注销并登录时:
当我有 getProducts 并将产品添加到集合时,此函数会渲染 (render()) 产品两次,但添加到集合一次。当我更新预算时,返回预算,但之后返回 0(在显示预算 a 的 DOM 上可以看到“Infinity”)
还有一件事,当我注销时,控制台返回错误:
TypeError: callback is not a function
at eval (index.js:182)
at Array.forEach (<anonymous>)
at Object.eval [as next] (index.js:182)
at eval (index.cjs.js:1226)
at eval (index.cjs.js:1336)
我认为这是因为 getProducts 和 updateBudget 不会返回取消订阅,而是未定义。
也许有人对此有解决方案?
推荐阅读
- scala - 如何为边缘添加属性?
- python - 无法使用烧瓶框架从 python 脚本呈现 html 页面中的列表值
- javascript - 使用 Karma 进行单元测试
- powerbi - 高于平均水平的人数
- vue.js - 选择选项后如何使用 element-ui 和 vuejs 触发“选择”的模糊事件?
- php - 如何在高级自定义字段中使用 Wordpress 图像大小
- powerbi-embedded - 在 Power BI Embedded 中筛选数据
- task - 任务参数作为下拉列表
- android - 使用间接 Getter 进行数据绑定 @Bindable
- wpf - 与 WPF 连接的身份服务器