使用pg-promise进行同步编程

8

我刚接触node.js和pg-promise,由于之前做的都是同步编程,所以需要重新思考。

我想从运行数据库初始化开始,了解程序逻辑的主要内容。

可以参考下面的例子: https://github.com/vitaly-t/pg-promise/wiki/Learn-by-Example#simple-select

db.any("select * from users where active=$1", [true])
  .then(function (data) {
    // success;
  })
  .catch(function (error) {
    // error;
  });

我的代码会被读作下面哪一个?
db.query("DELETE FROM records")
  .then(function (data) {
    // success;
    console.log("This is where all my main logic goes");
  })
  .catch(function (error) {
    // error;
  });

或者读作:

db.query("DELETE FROM records")
  .then(function (data) {
    // success;
  })
  .catch(function (error) {
    // error;
  });
console.log("This is where all my main logic goes");

我的理解是,使用后者的话,在记录删除之前消息将被显示。

更新: 阅读了许多关于promises和callbacks的文章后,我理解pg-promise使用链式调用来处理成功和错误的情况,即.then和.catch。我现在也相信,pg-promise命令应该放在类似以下的函数包装器中:

function initialiseDB() {
  db.query("DELETE FROM records")
    .then(function (data) {
      // success;
    })
    .catch(function (error) {
      // error;
    });
  }

在我的代码中,我会通过一个简单的命令异步调用这个函数:

initialiseDB();

然而,我仍然不确定异步编程和Promise的概念如何适用于程序的整体结构,因为几乎程序中的所有内容都需要先完成初始化。因此,整个程序不需要放在函数的“.then”部分中吗?也就是说,顶层唯一的代码实际上将是initializeDB()函数?

// Start of code here 
var pgp = require('pg-promise')();

//Configure the database connection
var config = {
  user:               'username', //env var: PGUSER 
  database:           'database', //env var: PGDATABASE 
  password:           'password', //env var: PGPASSWORD 
};

var db = pgp(config);

function initialiseDB() {
  db.query("DELETE FROM records")
    .then(function (data) {
      // This is where the main program logic goes after this line;
    })
    .catch(function (error) {
      // error;
    });
}

// Commence the program here
initialiseDB();

这是第一个。你应该阅读有关 Promise 的正确使用的信息,现在有很多相关资料可供参考,例如 PromiseJS - vitaly-t
谢谢,这对我来说都是新的。早期Node尝试了一个叫做“Promises”的功能,它添加了许多特性,使异步代码看起来更线性化。由于一些原因,它已经被从Node核心中移除了。 - Dercni
这是一篇糟糕的文章,甚至提出了像那样的无聊观点。Promises 是如今编写异步代码的最佳方式。 - vitaly-t
你可以在这里找到我的评论:https://github.com/maxogden/art-of-node/issues/67 - vitaly-t
感谢澄清,对于新手来说,在学习新技术的同时还要在矛盾信息的海洋中进行过滤,这一切都非常令人困惑。 - Dercni
1个回答

3
PG Promise实际上允许在较新的nodejs版本上使用生成器异步/等待生成器需要具有承诺的适配器,这是系统中必不可少的,因此提供生成器函数将允许以同步方式清晰地流动代码。

摘自标签任务下的存储库

没有生成器

db.task(t => {
        // this.ctx = task config + state context;
        return t.one('SELECT * FROM users WHERE id = $1', 123)
            .then(user => {
                return t.any('SELECT * FROM events WHERE login = $1',user.name);
            });
    })
    .then(events => {
        // success;
    })
    .catch(error => {
        // error;
    });

使用生成器(generators):
db.task(function * (t) {
        // this.ctx = task config + state context;
        let user = yield t.one('SELECT * FROM users WHERE id = $1', 123);
        return yield t.any('SELECT * FROM events WHERE login = $1', user.name);
    })
    .then(events => {
        // success;
    })
    .catch(error => {
        // error
    });

如果使用async/await,你可以用async function (t) 代替 function * (t),并用await 代替 yield,这样也能做到同样的效果。
需要注意以下几点:
在更复杂的逻辑中,你应该在可能出错的地方使用try catch块,因为在generatorsasync/await 中它们会将错误向上冒泡。
db.task(function * (t) {
    yield Promise.reject(new Error('This will cause your app to error')
}

你也应该注意他的pg-promise演示! 它将教你很多伟大的东西,比如扩展事件、repos、外部SQL文件以及库中其他伟大的内容(如helpers)!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接