使用node.js并承诺获取分页数据

时间:2017-07-04 10:20:23

标签: node.js promise pg-promise

请记住,我是node.js的新手,我和android开发一起使用。

我的情况是这样的:

  1. 对返回null或值
  2. 的数据库运行查询
  3. 使用该数据库值调用Web服务,该数据提供了分页信息,这意味着如果有更多信息要提取,我会在调用时获得一个参数来传递下一个调用。
  4. 检索完所有项目后,将它们存储在数据库表格中
  5. 如果一切顺利,对于之前收到的每件商品,我需要再打一次网络电话并将检索到的信息存储在另一张表中
  6. 如果获取任何数据集失败,则必须从数据库中还原所有数据
  7. 到目前为止,我已经尝试过这个:

    getAllData: function(){
      self.getMainWebData(null)
         .then(function(result){
           //get secondary data for each result row and insert it into database
       }
    }
    
    
    getMainWebData: function(nextPage){
        return new Promise(function(resolve, reject) {
    
          module.getWebData(nextPage, function(errorReturned, response, values) {
    
        if (errorReturned) {
              reject(errorReturned);
            }
    
            nextPage = response.nextPageValue;
            resolve(values);
          })
        }).then(function(result) {
    
        //here I need to insert the returned values in database     
    
          //there's a new page, so fetch the next set of data
          if (nextPage) {
              //call again getMainWebData? 
              self.getMainWebData(nextPage)
          }
    
        })
    

    从我测试过的内容中缺少一些东西,getAllData。然后只针对第一组项目而不针对其他项目触发一个,所以很明显地处理返回的数据不正确。

    后期编辑:我已编辑了该方案。考虑到更多的研究,我的感觉是我可以使用链或.then()来按顺序执行操作。

2 个答案:

答案 0 :(得分:2)

是的,这是因为你正在解决第一次通话本身的承诺。您应该将resolve(value)放在if语句中,该语句检查是否需要获取更多数据。您还需要重新构造逻辑,因为节点是异步的。除非您更改逻辑,否则上述代码将无效。

解决方案1:

您可以将分页响应附加到您正在进行的调用的上下文之外的另一个变量。然后在完成响应后使用该值。

getAllData: function(){
  self.getMainWebData(null)
  .then(function(result){
       // make your database transaction if result is not an error
   }
}

function getList(nextpage, result, callback){
  module.getWebData(nextPage, function(errorReturned, response, values) {
    if(errorReturned)
      callback(errorReturned);
    result.push(values);
    nextPage = response.nextPageValue;
    if(nextPage)
      getList(nextPage, result, callback);
    else
      callback(null, result);
  })
}
getMainWebData: function(nextPage){
  return new Promise(function(resolve, reject) {
    var result = [];
    getList(nextpage, result, function(err, results){
      if(err)
        reject(err);
      else{
        // Here all the items are retrieved, you can store them in a database table
        //  for each item received make your web call and store it into another variable or result set 
        // suggestion is to make the database transaction only after you have retrieved all your data 
        // other wise it will include database rollback which will depend on the database which you are using
        // after all this is done resolve the promise with the returning value
        resolve(results); 
      }
    });
  })    
}

我没有测试过,但是这样的事情应该有效。如果问题仍然存在,请在评论中告诉我。

解决方案2:

您可以删除promises并使用回调尝试相同的操作,因为它们更容易理解,并且对熟悉结构语言的程序员有意义。

答案 1 :(得分:1)

看看你的问题,我创建了一个循环承诺的代码。 并且只有在需要提取更多数据时才会进行,存储的数据仍然可以在数组中使用。 我希望这有帮助。不要忘记标记它是否有帮助。

let fetchData = (offset = 0, limit= 10) => {
    let addresses = [...Array(100).keys()];
    return Promise.resolve(addresses.slice(offset, offset + limit))
}
// o => offset & l => limit
let o = 0, l = 10;
let results = [];
let process = p => {
  if (!p) return p;
  return p.then(data => {
    // Process with data here;
    console.log(data);
    // increment the pagination
    o += l;
    results = results.concat(data);
    // while there is data equal to limit set then fetch next page 
    // otherwise return the collected result
    return (data.length == l)? process(fetchAddress(o, l)).then(data => data) : results;
  })
}
process(fetchAddress(o, l))
.then(data => {
    // All the fetched data will be here
}).catch(err => {
// Handle Error here.
// All the retrieved data from database will be available in "results" array 
});

如果您想要更频繁地执行此操作,我还创建了gist以供参考。 如果您不想使用任何全局变量,并希望以非常实用的方式执行它。您可以查看example。然而,它需要更多的复杂性。