在自建ghost blog的elasticsearch的文章中,我们已经看到了回调地狱(callback hell!!!),这真是个恐怖至极的东西。

应该有更优雅的方式来直接把ghost blog的内容导入elasticsearch吧。

我们来看一看:

先装需要的库,这里假设ghost用得是sqlite3的库,如果是mysql,需要修改下!

# mkdir /home/ex
# cd /home/ex
# npm install async
# npm install request
# npm install sqlite3
# cat /home/ex/run02.js
var util = require("util");  
var sqlite3 = require("sqlite3");  
var async = require("async");  
var request = require("request");

function main() {  
  // validate commandline params
  if(process.argv.length < 4) {
    console.log(util.format("Usage: %s %s <sqlite file path> <elastic search url>",
      process.argv[0], process.argv[1]));
    return;
  }

  var dbFile = process.argv[2];
  var searchUrl = process.argv[3];

  // load all posts
  loadPosts(dbFile, function(err, rows) {
    if(err) {
      console.dir(err);
      return;
    }

    // index all posts
    indexPosts(searchUrl, rows, function(err, results) {
      console.dir(arguments);
    });
  });
}

function indexPosts(url, posts, cb) {  
  async.each(posts, function(post, callback) {
    request({
      uri: url + post.id.toString(),
      method: "PUT",
      json: post
    }, function(err, res, body) {
      if(!err) {
        console.dir(body);
      }

      callback(err, {res: res, body: body});
    })
  }, function(err, results) {
    if(cb) {
      cb(err, results);
    }
  });
}

function loadPosts(file, cb) {  
  var db = new sqlite3.Database(file, sqlite3.OPEN_READONLY, function(err) {
    if(err) {
      cb(err);
      return;
    }

    db.all("select id, title, slug, markdown, html from posts", function(err, rows) {
      cb(err, rows);
    });
  })
}

main();  

对node小白来说,详细解释一下。

首先说一下同步和异步: 同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。

众所周知,异步是nodejs中得天独厚的特点和优势,但同时在程序中同步的需求(比如控制程序的执行顺序为:func1 -> func2 ->func3 )也是很常见的,这里我们用到了async的异步流程控制库。

async.each解释:
each: 如果想对同一个集合中的所有元素都执行同一个异步操作。

这个程序其实蛮恐怖,load所有的posts之后,狂发N个请求,然后返回同一个异步操作结果。

comments powered by Disqus