【问题标题】:How do I best handle this pagination with asynchronous Node.js?我如何最好地使用异步 Node.js 处理这种分页?
【发布时间】:2017-02-25 16:20:45
【问题描述】:

我的问题涉及到异步代码的使用。

这是相关的伪代码:

function handleQueryMore(result) {
    conn.queryMore(result.nextRecordsUrl, function(err, resultMore){    
        if (err) {}
        //do stuff with result
        if (!resultMore.done){
            handleQueryMore(resultMore);
        }
    });
}

//(below code runs first when launched of course)

var conn = new jsforce.Connection({////etc
var sql = "SELECT //.......

conn.query(sql, function(err, result) {
    if (err) {}
    //do stuff with result

    if (!result.done) //didn't pull all records
    {
        handleQueryMore(result);
    }               
});

初始查询只返回一定的最大记录数,然后递归调用 handleQueryMore() 来处理每个额外的记录块。

最初我在 where (!result.done){} 循环中有一个 conn.query(),但当然问题是 conn.query() 代码异步运行并且在下一次循环运行之前没有机会完成(导致〜无限的无目的循环)。

有 3rd 方库方法可以让代码同步运行,但我的猜测是我没有遵循一些基本的设计范例。递归有效,但我担心如果查询返回大量记录可能需要的内存量。

即使我知道需要分页的记录数,我也必须使用 result.nextRecordsUrl 进行分页,在执行之前的每个查询之前我无法获得...所以我不能只运行它们都在同一时间。

有人愿意参与进来吗?

谢谢!

【问题讨论】:

    标签: node.js asynchronous


    【解决方案1】:

    使用async.js 包。

    function handleQueryMore(result) {
    
      conn.queryMore(result.nextRecordsUrl, function(err, resultMore) {
        if (err) {}
        //do stuff with result
        else {
          async.each(result.data, function(individualData, callback) {
            // do some async task
            callback(); // to tell that this is completed
            //callback(err); if there is any error while processing data
          }, function(error) {
            if (!error) {
              if (!result.done) //didn't pull all records
              {
                handleQueryMore(result);
              }
            }
          });
        }
      });
    
    
    }
    
    
    
    var conn = new jsforce.Connection({ ////etc
      var sql = "SELECT //.......
    
      conn.query(sql, function(err, result) {
        if (err) {} else {
          async.each(result.data, function(individualData, callback) {
            // do some async task
            callback(); // to tell that this is completed
            //callback(err); if there is any error while processing data
          }, function(error) {
            if (!error) {
              if (!result.done) //didn't pull all records
              {
                handleQueryMore(result);
              }
            }
          });
        }
      });
    });
    

    【讨论】:

    • 感谢您简洁而相关的回答!我明天试试这个并跟进。
    【解决方案2】:

    我根本不会那样做。当您获得更大的数据集时,它的效率非常低。相反,我会接受查询字符串参数,这些参数指示我想要开始的记录索引和要返回的计数。所有数据库都有一个等效的skip and take(例如,如果您使用jsforce方法链API,您可以执行.skip(5).take(10) 以返回一组中的记录6-16)。这大大简化了您的代码并通过使每个请求独立于其他请求来降低风险。

    另外,我注意到//(below code runs first when launched of course) 的评论,但这也不是一个好主意。理想情况下,您希望按需查询数据库,而不是在应用启动时。这也可能是您遇到挑战的原因。

    【讨论】:

    • 这是redux代码; “真正的”代码有一个“main”,它调用有问题的代码。当我回到我的工作站时,我会检查是否存在跳过/拍摄
    • 这不是我的意思,Juan,我的意思是在大多数情况下,查询应该发生在客户端请求上,除非它是您的应用程序正在缓存并且很少更改的信息。
    • 我现在明白你的意思了。这是一个批处理过程,将由调度程序触发,因此不涉及客户端。
    • 如果您发布了实际代码的相关部分并更好地描述了您正在尝试做什么,这可能会很有用。基于伪代码且没有目标,很难正确回答。
    • 感谢您的建议。我不应该将其称为伪代码,除了 SQL 语句和缺少“要求”语句之外,该代码是完全可运行的,并且仅包含与我的问题相关的部分。很抱歉,我没有明确提到它不是客户驱动的;我是 Node.js 的新手,并不认为这是假设。也就是说,您说 jsforce 确实支持跳过/获取似乎是正确的,尽管它似乎需要查询方法链接,这很好,但需要重新处理查询。我会检查一下。谢谢!
    【解决方案3】:

    嗨,如果你使用的是 mongo db,那么试试这个..

       user.aggregate({ $match: { status: true, type: req.query.type } },
            { "$skip": (skipValue) }, { "$limit": limitValue },
            (err, data) => {
    //Code
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-29
      • 2012-12-27
      • 2015-11-23
      • 1970-01-01
      • 2020-11-08
      • 2018-08-13
      相关资源
      最近更新 更多