前两天公司一哥们写了一段node.js代码发给我,后面特意提了一句“写的不太优雅”。我知道,他意思是回调嵌套回调,因为当时比较急也就没有再纠结。然而内心中总记得要解决这个问题。解决node.js的回调金字塔问题有较多方法,在《深入浅出node.js》这本书中介绍了好几种,有事件发布/订阅模式、Promise模式、async库等。其中Promise模式被很多人推崇,实现的库有很多,本着从众的原则,闭着眼睛选个bluebird吧。

然而bluebird的文档并不咋滴,相当不咋滴!网上的例子基本上都是fs.readFile方法的示例,鲜有其他例子。为了更好的理解和使用bluebird,只能自已动手试一下咯。本文本着实用的目的,主要介绍如何将自定义方法转换为Promise方法,将异步方法转换为同步方法调用。

1. 首先定义一些简单的方法,这是一个很简单例子,模拟读取配置文件、打开数据库、创建数据库结构、创建一个用户、读取这个用户、显示这个用户属性的整个过程。此处就不写node.js的回调嵌套了,以免使用手机打开本文时特别惨不忍睹的。

 1 //数据库对象
 2 var db;
 3 
 4 //使用配置文件获取连接字符串
 5 var getConn = function(cfg){
 6 }
 7 
 8 //创建或打开sqlite3数据库
 9 var openDb =  function(dbConn){
10 }
11 
12 //创建数据库结构
13 var createSchema = function(){
14 }
15 
16 //创建用户
17 var createUser = function(){
18 }
19 
20 //获取用户
21 var getUser = function(id){
22 }
23 
24 //显示用户属性
25 var showUser = function(user){
26 }

2. 首先来看使用bluebird怎么将异步方法变成同步方法执行

"use strict";

var fs = require("fs");
var sqlite3 = require("sqlite3");
var Promise = require("bluebird");

const conn = "conn.txt";
var db;

var getConn = function(cfg){
    return new Promise(function(resolve, reject){
        fs.readFile(cfg, "utf-8", function(err, data){
            if(err){
                reject(err);
            } else {
                console.log("db: ".concat(data));
                resolve(data.trim());
            }
        });
    });
}

var openDb = function(dbConn){
    return new Promise(function(resolve, reject){
        db = new sqlite3.Database(dbConn, function(err){
            if(err){
                reject(err);
            } else{
                console.log("open database");
                resolve();
            }
        });
    });
}

var createSchema = function(){
    return new Promise(function(resolve, reject){
        db.serialize(function(){
            var createExpsTable = "CREATE TABLE IF NOT EXISTS expressions ('name' NVARCHAR(20), 'expression' TEXT, 'index' INT, 'likes' INT)";
            var createUserTable = "CREATE TABLE IF NOT EXISTS users ('name' NVARCHAR(20), 'password' VARCHAR(20))";
            db.exec(createExpsTable, function(err){
                if(err){
                    reject(err);
                } else {
                    console.log("create table expressions");
                }
            });

            db.exec(createUserTable, function(err){
                if(err){
                    reject(err);
                } else {
                    console.log("create table users");
                    resolve();
                }
            });
        });
    });
}

var createUser = function(){
    return new Promise(function(resolve, reject){
        db.run("INSERT INTO users (name, password) VALUES ($name, $password)", {$name: "think8848", $password: "111111"}, function(err){
            if(err){
                reject(err);
            } else{
                console.log("createUser");
                resolve(this.lastID);
            }
        });
    });
}

var getUser = function(id){
    return new Promise(function(resolve, reject){
        db.get("SELECT rowid, name, password FROM users WHERE rowId = $id", {$id: id}, function(err, row){
            if(err){
                reject(err);
            } else {
                console.log("getUser");
                resolve(row);
            }
        });
    });
}

var showUser = function(user){
    console.log("id: ".concat(user.rowid).concat(", name: ").concat(user.name).concat(", password: ").concat(user.password));
}

getConn(conn)
.then(openDb)
.then(createSchema)
.then(createUser)
.then(getUser)
.then(showUser)
.catch(function(err){
    console.log(err.message);
});
View Code

相关文章: