Функция ParseServer Cloud Code завершается до выполнения обещания - PullRequest
0 голосов
/ 05 октября 2018

У меня есть сценарий, в котором я пытаюсь определить, сколько новых «плательщиков» у компании за текущий месяц.Код у меня работает, я могу зарегистрировать результаты и получить количество ожидаемых новых плательщиков для компании.Однако метод возвращает 0, потому что окончательный код выполняется до завершения Promise.

Мне кажется, проблема в том, что обещания не связаны, а вложены, я пытался их объединить, но он просто выдавал ошибки.Что-то явно не так с кодом ниже?

Parse.Cloud.define('cloudMethod', function(request, response) {
  if (!request.user) {
    response.error('Invalid User')
    return
  }

  // Set up now date
  const now = new Date()
  const thisMonthYear = now.getMonth().toString() + now.getFullYear().toString()

  // Setup empty array to hold new monthly payer matches
  const newMonthlyDonors = []

  // Setup User query
  const User = Parse.Object.extend('User')
  const userQuery = new Parse.Query(User)

  // Step 1: Get company pointer from user
  userQuery
    .equalTo('username', request.user.get('username'))
    .first()
    .then(function(user) {

      // Step 2: Count payers for that company
      var Payment = Parse.Object.extend('Payment')
      var paymentQuery = new Parse.Query(Payment)
      paymentQuery.equalTo('company', user.get('company'))

      // Create a trivial resolved promise as a base case.
      var promise = Parse.Promise.as()

      paymentQuery.distinct('user').then(function(results) {
        // Step 3: Loop through each distinct payer
        _.each(results, function(result) {
          // For each item, extend the promise with a function.
          promise = promise.then(function() {
            // Setup new Payment query
            const firstPaymentQuery = new Parse.Query(Payment)

            /*
              Step 4:
              Query Payment class by this user,
              set payment dates in ascending order
              and then take the first one.
            */
            firstPaymentQuery
              .equalTo('user', result)
              .ascending('paymentDate')
              .first()
              .then(function(firstPayment) {
                // Set up user date
                const firstPaymentDate = new Date(firstPayment.get('paymentDate'))
                const firstPaymentMonthYear = firstPaymentDate.getMonth().toString() + firstPaymentDate.getFullYear().toString()

                /*
                Step 5:
                See if the user's first payment date is equal to the current month
                */
                if (firstPaymentMonthYear === thisMonthYear) {
                  return newMonthlyDonors.push(result)
                }
                else {
                  return
                }
              }, function(error) {
                response.error('Query to get users first payment date failed')
              })
          })
        })

        return promise
      }).then(function() {
        /*
          FIXME:
          This is getting called before the queries above can run.
          Which is why it's returning 0...
        */

        // Return the matches for this month
        response.success(newMonthlyDonors.length)
      }, function(error) {
        response.error('total user count for company failed')
      })
  },
  function(error) {
    console.log('Error retrieving User')
    console.log(error)
  })
})

Ответы [ 2 ]

0 голосов
/ 09 ноября 2018

Проблема заключалась в том, что я не возвращал запрос как результат первого обещания, вызванного в _.each(), поэтому возвращенный результат в этом запросе никогда не возвращался.

Ссылка на большой блок кода ввопрос:

Это:

/*
  Step 4:
  Query Payment class by this user,
  set payment dates in ascending order
  and then take the first one.
*/
firstPaymentQuery…

Нужно быть таким:

/*
  Step 4:
  Query Payment class by this user,
  set payment dates in ascending order
  and then take the first one.
*/
return firstPaymentQuery…
0 голосов
/ 05 октября 2018

Я бы рассмотрел создание массива, содержащего все ваши обещания const promises = [];, поэтому каждый раз, когда у вас есть обещание, вы помещаете его в массив.

Затем вы возвращаете все обещания, как это: return Promise.all(promises);

Parse.Cloud.define('cloudMethod', function(request, response) {

    ...

    const promises = [];

    promises.push(firstPaymentQuery
          .equalTo('user', result)
          .ascending('paymentDate')
          .first()
          .then(function(firstPayment) { ...

    );

    ...

    // callback if all promises have finished
    Promise.all(promises).then(() => {
        // success
    });

});

Это то, чем я обычно занимаюсь.

...