簡體   English   中英

Firebase 添加/刪除數據時,應用會多次執行功能

[英]Firebase when add/delete data, app do functions more than once

我的貨幣應用程序有問題。 當我從我的應用程序(產品集合)中添加/刪除數據時,我的應用程序執行多個“sumPrices()”函數。 例如:當我添加一個產品時,制作一次,添加另一個產品,制作兩次,添加另一個產品制作三個等等。這與刪除數據的方式相同。

在我的代碼中做錯了什么?

Callback.push 推送數據做數組,我從 firebase 取消訂閱事件。 AddStatsUI 將 UI 添加到我的 DOM。

索引.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 = '';
}};

};

導出默認統計信息;

我將 console.log 添加到 sumPrices

應用截圖,當我添加 2 個產品並嘗試更新預算時

好的,對我的代碼進行了一些改進,但仍然存在訂閱問題。 現在一切正常,但是當我注銷並登錄函數 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(在 DOM 上顯示預算 a 可以看到“無限”)

還有一件事,當我注銷時,控制台返回錯誤:

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 不返回取消訂閱,而是返回未定義。

也許有人對此有解決方案?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM