I'm trying to write a small library with re-usable database calls with nano.

db.view('list', 'people', function(error, data) {
  if (error == null) {
    res.render('people/index', {
      people: data.rows
    });
  } else {
    // error
  }
});

That can get quite messy when having multiple requests:

db.view('list', 'people', function(error, people) {
  db.view('list', 'items', function(error, items) {
    db.view('list', 'questions', function(error, questions) {
      db.view('list', 'answers', function(error, answers) {
        ...
        res.render('people/index', {
          people: people.rows,
          items: items.rows,
          questions: questions.rows
          ...

So, the idea was to create a function:

var getPeople = function() {
  // do db calls here and return
}

res.render('people/index', {
  people: getPeople()
});

But that doesn't work.

How can I solve this and put everything into an external node-js-module.js file?

有帮助吗?

解决方案

You got some great answers here already.

From the nano source code you have an example that might help:

Also if you don't really understand how nodejs flow control works I can't recommend enough that you see this tutorial:

Better than using a tool is to use the tool understanding how it works :) Maybe you'll end up just coding your own control flow, that's what most of us ends up doing anyway.

Hope this helps, attached code for convenience.

  var db    = require('nano')('http://localhost:5984/emails')
    , async = require('async')
    ;

  function update_row(row,cb) {
    var doc = row.doc;
    delete doc.subject;
    db.insert(doc, doc._id, function (err, data) {
      if(err)  { console.log('err at ' + doc._id);  cb(err); }
      else     { console.log('updated ' + doc._id); cb(); }
    });
  }

  function list(offset) {
    var ended = false;
    offset = offset || 0;
    db.list({include_docs: true, limit: 10, skip: offset}, 
      function(err, data) {
        var total, offset, rows;
        if(err) { console.log('fuuuu: ' + err.message); rows = []; return; }
        total  = data.total_rows;
        offset = data.offset;
        rows   = data.rows;
        if(offset === total) { 
          ended = true;
          return; 
        }
        async.forEach(rows, update_row, function (err) {
          if(err) { console.log('something failed, check logs'); }
          if(ended) { return; }
          list(offset+10);
        });
    });
  }

  list();

其他提示

I would suggest caolan's aysnc library. Very easy to use, and it works on both browser and in couch with require (not that you will be using on the couch side to query).

For the particular problem you can use series or waterfall:

Have you considered view collation of your views in CouchDB? This would help you to reduce the number of db.view(..) calls and return all the data you need in 1 view query. It's pretty easy for a single one-to-many (ie; 'person' has many 'items'). It maybe a little more effort for multiple levels, but it should work the same way. There are some good articles on Couch view collation here:

CouchDB Joins

CouchDB View Collation

The best solution I know of, is to use promises. It takes a little bit to get used to, but it's well worth the effort. I'm using Kris Kowal's Q-library. He gave a good walk-through of the Q API's and design at JSConf-2010 (jump to 15:30).

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top