Parse Server Cloud Code 函数在 promise 实现之前完成

ParseServer Cloud Code function finishing before promise has been fulfilled

我有一个场景,我试图确定一家公司当月有多少新 "payers"。我的代码有效,我可以记录结果并获得公司预期的新付款人数量。但是,该方法返回 0,因为最终代码是在 Promise 完成之前执行的。

我认为问题是 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)
  })
})

我会考虑创建一个包含您所有承诺的数组 const promises = [];,因此每次您有一个承诺时,您都将其放入数组中。

那么你return所有的承诺都是这样的: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
    });

});

这是我经常做的。

问题是我没有返回查询作为 _.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…