首页 > 解决方案 > Array.map() 的异步回调

问题描述

几周前我刚刚开始学习 Node.js....我无法理解为什么“产品”数组包含null而不是所需的对象....

在第 13 行,当我在控制台记录对象时,我得到了所需的对象,但我不明白为什么当我在地图函数完成执行后在第 40 行控制台记录它们时它们为空......

如果数组长度为 2(这应该意味着成功推送),为什么存储在里面的对象仍然为,而不是我想要存储的对象?

控制台输出

控制台输出

订单模式

订单模式

exports.getOrders = async (req, res, next) => {
  const userOrders = [];
  Order.find({ 'user.userId': req.user._id }).then((orders) => {
    console.log(orders); // Line 4
    async.eachSeries(
      orders,
      function (order, callback) {
        const products = order.products.map((p) => {
          const seriesId = p.product.seriesId;
          const volumeId = p.product.volumeId;
          Series.findById(seriesId).then((series) => {
            const volume = series.volumes.id(volumeId);
            console.log(volume, p.quantity); // Line 13
            return {
              seriesTitle: volume.parent().title,
              volume: volume,
              quantity: p.quantity
            };
          });
        });
        console.log('Product Array Length: ', products.length); // Line 21
        if (products.length !== 0) {
          const data = {
            productData: products,
            orderData: {
              date: order.date,
              totalPrice: order.totalPrice
            }
          };
          userOrders.push(data);
          callback(null);
        } else {
          callback('Failed');
        }
      },
      function (err) {
        if (err) {
          console.log('Could not retrieve orders'); 
        } else {
          console.log(userOrders);  // Line 40
          res.render('shop/orders', {
            docTitle: 'My Orders',
            path: 'orders',
            orders: userOrders,
            user: req.user
          });
        }
      }
    );
  });
};

标签: javascriptnode.jsasynchronousasync.js

解决方案


在第 8 行,order.products.map返回一个空数组。因为这是一个异步映射。对于每个产品,您调用Series.findById的都是一个承诺,它只在解析时返回值。由于您不等待承诺解决,因此它在每次迭代时返回 null 。

您必须先映射所有承诺,然后调用Promise.all以解决它们,然后您将获得预期值。

exports.getOrders = async (req, res, next) => {
  const userOrders = [];
  Order.find({ 'user.userId': req.user._id }).then((orders) => {
    console.log(orders); // Line 4
    async.eachSeries(
      orders,
      function (order, callback) {
        const productPromise = order.products.map((p) => {
          const seriesId = p.product.seriesId;
          const volumeId = p.product.volumeId;
          //ANSWER:  Return the following promise
          return Series.findById(seriesId).then((series) => {
            const volume = series.volumes.id(volumeId);
            console.log(volume, p.quantity); // Line 13
            return {
              seriesTitle: volume.parent().title,
              volume: volume,
              quantity: p.quantity
            };
          });
        });
        // ANSWER: call all the promises
        Promise.all(productPromise)
        .then(function(products) {
            console.log('Product Array Length: ', products.length);
            if (products.length !== 0) {
            const data = {
              productData: products,
              orderData: {
                date: order.date,
                totalPrice: order.totalPrice
              }
            };
            userOrders.push(data);
            callback(null);
          } else {
            callback('Failed');
          }
        });
      },
      function (err) {
        if (err) {
          console.log('Could not retrieve orders'); 
        } else {
          console.log(userOrders);  // Line 40
          res.render('shop/orders', {
            docTitle: 'My Orders',
            path: 'orders',
            orders: userOrders,
            user: req.user
          });
        }
      }
    );
  });
};


推荐阅读