Облачные функции: избегайте вложенных обещаний для разных условий - PullRequest
0 голосов
/ 11 апреля 2020

Я пытаюсь написать функцию, которая учитывает 3 условия при каждом срабатывании Stores/{storeId}/{departmentId}/{productId}, и записать новые данные в ref.child('Home').child('Chiep').child(departmentId).child(productId).

1) Когда в firestore нет данных, я необходимо заполнить все поля в Realtime DB, сделав запросы в 2 разных узлах firestore: Stores и Products, чтобы получить их изображения.

2) При изменении сделано в узле Stores и происходит из того же {storeId}, мне просто нужно обновить некоторые данные, не делая дополнительных запросов.

3) И наконец, когда в Stores вносятся изменения узел, и он поступает из другого {storeId}, мне нужно сделать только один запрос в узле Stores.

exports.homeChiepest = functions.firestore
.document('Stores/{storeId}/{departmentId}/{productId}')
.onWrite((change, context) => {

  const storeId = context.params.storeId;
  const departmentId = context.params.departmentId;
  const productId = context.params.productId;
  const ref = admin.database().ref();

  // Get an object with the current document value.
  // If the document does not exist, it has been deleted.
  const document = change.after.exists ? change.after.data() : null;

  // Get an object with the previous document value (for update or delete)
  const oldDocument = change.before.exists ? change.before.data() : null;

  // Prevent infinite loops
  if (!change.after.exists) {
    console.log('DATA DELETED RETURN NULL');
    return null;
  }

  const newPrice = document.price;
  const newTimestamp = document.timestamp;

  return ref.child('Home').child('Chiep')
  .child(departmentId).child(productId)
  .once('value')
  .then(dataSnapshot => {

    if (dataSnapshot.val() !== null) {

      console.log('CHIEP DOES exist');

      const oldPrice = dataSnapshot.val().price;
      const storeKey = dataSnapshot.val().storeKey;
      if (storeId === storeKey) {
        console.log('SAME STORE - Change price and timestamp');
        var newChiepest = {
          timestamp: newTimestamp,
          price: newPrice
        };
        return dataSnapshot.ref.update(newChiepest);

      } else {
        console.log('OTHER STORE - Verify if price is chieper...');
        if (newPrice <= oldPrice) {
          console.log('NEW PRICE: '+newPrice+' is chieper than the older one: '+oldPrice);

          return change.after.ref.parent.parent.get().then(doc => { // HERE Avoid nesting promises
            newStoreImg = doc.data().image;
            var newStoreChiep = {
              price: newPrice,
              storeImg: newStoreImg,
              storeKey: storeId,
              timestamp: newTimestamp
            };
            return dataSnapshot.ref.update(newStoreChiep);

          });

        } else {
          console.log('NEW PRICE: '+newPrice+' is mode EXPENSIVE than the older one: '+oldPrice);
        }
        return null;
      }

    } else {
      console.log('data does NOT exist, so WRITE IT!');

      let getStoreData = change.after.ref.parent.parent.get();
      let getProductData = admin.firestore().collection('Products').doc('Departments').collection(departmentId).doc(productId).get();

      return Promise.all([getStoreData, getProductData]).then(values => { // HERE Avoid nesting promises
        const [store, product] = values;
        var newHomeChiepest = {
          depId: departmentId,
          price: newPrice,
          prodImg: product.data().image,
          prodKey: productId,
          storeKey: storeId,
          storeImg: store.data().image,
          timestamp: newTimestamp
        };
        return dataSnapshot.ref.set(newHomeChiepest);

      });

    }


  })
  .catch(error => {
    console.log('Catch error reading Home: ',departmentId ,'/', productId,'; message: ',error);
    return false;
  });

});

Проблема в том, что разные возможности запрашивать или не запрашивать другой firestore приведенный узел при загрузке Clound Function предупреждения, а именно:

предупреждение Избегать вложенных обещаний обещание / отсутствие вложений

Я ценю любую помощь по рефакторингу этого кода.

1 Ответ

1 голос
/ 11 апреля 2020

Вы можете использовать переменную для управления «шунтированием», в зависимости от различных случаев, следующим образом (не проверено):

exports.homeChiepest = functions.firestore
    .document('Stores/{storeId}/{departmentId}/{productId}')
    .onWrite((change, context) => {

        const storeId = context.params.storeId;
        const departmentId = context.params.departmentId;
        const productId = context.params.productId;
        const ref = admin.database().ref();

        const document = change.after.exists ? change.after.data() : null;

        // Prevent infinite loops
        if (!change.after.exists) {
            console.log('DATA DELETED RETURN NULL');
            return null;
        }

        const newPrice = document.price;
        const newTimestamp = document.timestamp;

        let shunting;   // <-- We manage the shunting through this variable
        let chiepRef;

        return ref.child('Home').child('Chiep')
            .child(departmentId).child(productId)
            .once('value')
            .then(dataSnapshot => {

                chiepRef = dataSnapshot.ref;

                if (dataSnapshot.val() !== null) {

                    console.log('CHIEP DOES exist');

                    const oldPrice = dataSnapshot.val().price;
                    const storeKey = dataSnapshot.val().storeKey;
                    if (storeId === storeKey) {
                        shunting = 1
                        console.log('SAME STORE - Change price and timestamp');
                        var newChiepest = {
                            timestamp: newTimestamp,
                            price: newPrice
                        };
                        return chiepRef.update(newChiepest);

                    } else {
                        console.log('OTHER STORE - Verify if price is chieper...');
                        if (newPrice <= oldPrice) {
                            console.log('NEW PRICE: ' + newPrice + ' is chieper than the older one: ' + oldPrice);
                            shunting = 2

                            return change.after.ref.parent.parent.get();

                        } else {
                            console.log('NEW PRICE: ' + newPrice + ' is mode EXPENSIVE than the older one: ' + oldPrice);
                            shunting = 3
                            return null;
                        }

                    }

                } else {
                    console.log('data does NOT exist, so WRITE IT!');
                    shunting = 4;
                    let getStoreData = change.after.ref.parent.parent.get();
                    let getProductData = admin.firestore().collection('Products').doc('Departments').collection(departmentId).doc(productId).get();

                    return Promise.all([getStoreData, getProductData])

                }


            })
            .then(result => {

                if (shunting === 2) {
                    const newStoreImg = result.data().image;
                    var newStoreChiep = {
                        price: newPrice,
                        storeImg: newStoreImg,
                        storeKey: storeId,
                        timestamp: newTimestamp
                    };
                    return chiepRef.update(newStoreChiep);
                } else if (shunting === 4) {
                    const [store, product] = result;
                    const newHomeChiepest = {
                        depId: departmentId,
                        price: newPrice,
                        prodImg: product.data().image,
                        prodKey: productId,
                        storeKey: storeId,
                        storeImg: store.data().image,
                        timestamp: newTimestamp
                    };
                    return chiepRef.set(newHomeChiepest);
                } else {
                    return null;
                }

            })
            .catch(error => {
                console.log('may be adapted, function of shunting', error);
                return null;
            });

    });
...