You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js如何实现返回Sequelize查询结果数组的Promise函数?

Fixing Sequelize Async Function to Return a Promise and Access Results

Hey there! The core issue with your current getInvoicesCount function is that you're returning the promiseInvoices array synchronously, but Sequelize's findAll is an asynchronous operation—so the array is still empty when you return it. Let's adjust this to make the function return a Promise, so you can properly fetch the populated data with .then() in your main code.

Option 1: Modify with Promise Chains

We'll have the function return the entire findAll Promise chain, and return your final data array at the end of the chain:

function getInvoicesCount() {
  let userInvCount = 0;
  let deletedUserInvCount = 0;
  let userInvAmount = 0;
  let deletedUserInvAmount = 0;
  let monthWiseInvCount = [];

  // Return the Promise chain directly
  return db.userInvoices
    .findAll({
      attributes: [
        'deleted_at',
        [sequelize.fn('COUNT', sequelize.col('id')), 'count'],
        [sequelize.fn('SUM', sequelize.col('invoice_amount')), 'amount'],
        [sequelize.fn('MONTH', sequelize.col('invoice_date')), 'month']
      ],
      group: ['invoice_date', 'deleted_at'],
      paranoid: false
    })
    .then(result => {
      result.forEach(element => {
        const data = element.dataValues;
        userInvCount += data.count;
        userInvAmount += data.amount;
        
        if (data.deleted_at !== null) {
          deletedUserInvAmount += data.amount;
          deletedUserInvCount += data.count;
        }
        
        // Clean up the deleted_at field (fixed your original flawed map logic)
        const { deleted_at, ...monthData } = data;
        monthWiseInvCount.push(monthData);
      });

      // Return the final array to pass to .then()
      return [
        userInvCount,
        userInvAmount,
        deletedUserInvCount,
        deletedUserInvAmount,
        monthWiseInvCount
      ];
    })
    .catch(error => {
      // Don't forget to handle errors!
      console.error('Failed to fetch invoice data:', error);
      throw error; // Re-throw to let the caller handle it too
    });
}

Async functions automatically return a Promise, and this syntax is much cleaner for asynchronous logic:

async function getInvoicesCount() {
  let userInvCount = 0;
  let deletedUserInvCount = 0;
  let userInvAmount = 0;
  let deletedUserInvAmount = 0;
  let monthWiseInvCount = [];

  try {
    // Wait for the Sequelize query to complete
    const result = await db.userInvoices.findAll({
      attributes: [
        'deleted_at',
        [sequelize.fn('COUNT', sequelize.col('id')), 'count'],
        [sequelize.fn('SUM', sequelize.col('invoice_amount')), 'amount'],
        [sequelize.fn('MONTH', sequelize.col('invoice_date')), 'month']
      ],
      group: ['invoice_date', 'deleted_at'],
      paranoid: false
    });

    result.forEach(element => {
      const data = element.dataValues;
      userInvCount += data.count;
      userInvAmount += data.amount;
      
      if (data.deleted_at !== null) {
        deletedUserInvAmount += data.amount;
        deletedUserInvCount += data.count;
      }
      
      const { deleted_at, ...monthData } = data;
      monthWiseInvCount.push(monthData);
    });

    // Return the array—async function wraps it in a Promise
    return [
      userInvCount,
      userInvAmount,
      deletedUserInvCount,
      deletedUserInvAmount,
      monthWiseInvCount
    ];
  } catch (error) {
    console.error('Failed to fetch invoice data:', error);
    throw error;
  }
}

How to Call the Function and Access the Array

Now in your main code, you can use .then() to get the populated array, and even destructure it for easier access:

getInvoicesCount()
  .then(invoicesData => {
    // Destructure the array into individual variables
    const [
      userInvCount,
      userInvAmount,
      deletedUserInvCount,
      deletedUserInvAmount,
      monthWiseInvCount
    ] = invoicesData;

    // Use your data here
    console.log('Total invoices:', userInvCount);
    console.log('Total invoice amount:', userInvAmount);
    console.log('Deleted user invoices count:', deletedUserInvCount);
    console.log('Deleted user invoices amount:', deletedUserInvAmount);
    console.log('Month-wise invoice data:', monthWiseInvCount);
  })
  .catch(error => {
    // Handle any errors propagated from the function
    console.error('Error processing invoice data:', error);
  });

Quick Notes on Improvements

  • I fixed the logic to remove the deleted_at field from monthWiseInvCount—your original map approach wasn't working correctly, so destructuring is a more reliable solution.
  • Added error handling with .catch() (for Promise chains) and try/catch (for async/await) to avoid unhandled Promise rejections.
  • Async/await is generally easier to read and maintain, especially if you add more asynchronous steps later.

内容的提问来源于stack exchange,提问作者daksh bhardwaj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:12:27