Firebase при добавлении / удалении данных, приложение выполняет функции более одного раза - PullRequest
1 голос
/ 08 марта 2020

У меня проблемы с моим приложением денег. Когда я добавляю / удаляю данные из моего приложения (коллекции товаров), мое приложение выполняет функцию «sumPrices ()» более, чем в одном. Например: когда я добавляю один продукт, сделайте один продукт, добавьте другой продукт, сделайте дважды, добавьте еще один продукт, сделайте три и т.д. c. Это происходит так же, как и при удалении данных.

А что-то не так в моем коде?

Callback.pu sh pu sh массив данных, где я отписываю события от firebase. AddStatsUI добавляет пользовательский интерфейс в мой 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))

product. 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 продукта и пытаюсь обновить бюджет

1 Ответ

0 голосов
/ 14 марта 2020

Окей, добавьте некоторые улучшения в мой код, но все еще есть проблемы с подписками. Теперь все окейно, но когда я выхожу и авторизируюсь, функции 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 не возвращают отписку, но не определены.

Может быть, у кого-то есть решение для этого?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...