使用某些东西的通用方法' unmeasured'在Node.js中

时间:2016-11-17 11:15:55

标签: javascript node.js

NB :不要将其视为代码审核,我可以想象socket而不是REST API或任何其他数据源。问题是如何以JS方式解决这类任务

我使用了一些暴露某些项目的rest API。你可以通过偏移和计数来获取项目。但一次最多1000个。并且您无法查询项目数(您只能自己计算)

对于这种工作,我使用下面的代码:

const request = require('superagent')
const _ = require('lodash')
const bluebird = require('bluebird')

const STEP = 1000

function call(offset) {
  return bluebird.resolve(
    request
      .get('someapi/items')
      .auth('name', 'key')
      .query({
        offset: offset,
        languagecodes: ['en']
      })
  )
  .then((req) => req.body)
}

function grab(acc, offset) {
  acc = acc || []
  offset = offset || 0
  return call(offset)
    .then((items) => {
      doSomething(items)
      if(items.length < STEP) {
        return
      }
      return grab([], offset + STEP)
    })
}

grab().then(() => {
  finishDo()
}).catch(function(err) {
  console.log(err)
  throw err
})

它有效,但有一些问题:

  • 代码太具体了
  • 如果我需要任何类型的业务逻辑(聚合,过滤,转换),我需要将所有内容放在grab函数

那么,我怎样才能更好地重写这段代码呢?

2 个答案:

答案 0 :(得分:2)

以下是使用回调的示例

我也尝试使用蓝鸟,如果你没有在你的回调中返回一个承诺它仍然有用,这很方便,IOW:如果你愿意,你的回调也可以是承诺。

function grab(cb, acc, offset) {
  acc = acc || []
  offset = offset || 0
  return call(offset)
    .then((items) => {
      return bluebird.try(() = > cb(items)).then(() => {
        if(items.length < STEP) {
          return
        }
        return grab(cb, [], offset + STEP)
      })
    })
}

//To use..

grab((items) => { 
  //do something with items.
});

答案 1 :(得分:0)

我意识到我想要什么。实际上我可以将API答案视为一些流。它使我能够使用与收集相同的操作(缩小,过滤,映射)。 在使用highland.js创建和处理Node.js流的示例下面

const H = require('highland');

function grabApi() {
    let offset = 0
    return H(function (push, next) {
      call(offset).then(function(items) {
          push(null, items)
          if(items.length === STEP) {
            offset = offset + STEP
            next()
          } else {
            push(null, H.nil)
          }
      })
    })
};

grabApi() // now it's node-like stream
 .filter(/* some function */)
 .map(/* some function */)
 .each(function(x) { ...
 .done(function() { // when it'll end