Array.map() 的异步回调

Posted

技术标签:

【中文标题】Array.map() 的异步回调【英文标题】:Asynchronous Callback to Array.map() 【发布时间】:2021-06-24 03:36:22 【问题描述】:

几周前我刚刚开始学习 Node.js.... 我无法理解为什么 'products' 数组包含 null 而不是想要的对象....

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

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

控制台输出

订单架构

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
          );
        
      
    );
  );
;

【问题讨论】:

不要将 async.js 回调样式与 Promise 混用。您已经在使用async/await 语法,所以只需编写一个循环而不是使用async.eachSeries 【参考方案1】:

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

你必须先映射所有的promise,然后调用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
          );
        
      
    );
  );
;

【讨论】:

非常感谢您的解释,它有效.... ^__^

以上是关于Array.map() 的异步回调的主要内容,如果未能解决你的问题,请参考以下文章

同步回调函数与异步回调函数

php支付宝手机网站支付,异步回调和同步回调里面应该怎么写

异步回调函数

WPF异步回调时回调函数如何获取异步函数产生的变量

如何优雅的处理Nodejs中的异步回调

如何优雅的处理Nodejs中的异步回调