使用异步数据库编程排序操作

时间:2016-08-03 01:51:01

标签: node.js asynchronous pg-promise

异步和挣扎的新手。作为下面的示例,我希望初始化一个表,然后通过以下方式处理它的内容: a)删除旧数据 b)插入新记录 c)将表读入数组 d)显示数组

'use strict';


// ================================================================================
// Module dependencies
var pgp      = require('pg-promise')();


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


// ================================================================================
// Initialise rhe variables
var customers = [];


// ================================================================================
// Initialise table
db.none("DELETE FROM testing")
  .then(function(data) {
    console.log("Deleted old records");
    // success;
  })
  .catch(function(error) {
    console.log(error);
  });

db.none("INSERT INTO testing (firstname, surname) VALUES ('Bob', 'Brown')")
  .then(function(data) {
    console.log("Inserted new record");
    // success;
  })
  .catch(function(error) {
    console.log(error);
  });


// ================================================================================
// Display records
db.any("SELECT * FROM testing")
  .then(function(data) {
    console.log("Looping records");
    data.forEach(function(row, index, data) {
      customers.push(row.firstname, row.lastname);
      console.log(row);
    });
  })
  .catch(function(error) {
    console.log(error);
  });

console.log("The customers are:");
console.log(customers);

输出不是预期的,但有点像预期的那样。有趣的是,在“插入新记录”之后,在命令提示符重新调整之前有30秒的等待时间。

The customers are:
[]
Looping records
anonymous {
  id: 3,
  firstname: 'Bob',
  surname: 'Brown',
  created: 2016-08-03T01:43:34.880Z }
Deleted old records
Inserted new record

我的问题最终是异步编程肯定存在需要按顺序执行操作的情况,例如上面的示例,在这种情况下,如何在异步环境(如node.js)中编码。

2 个答案:

答案 0 :(得分:2)

由于您使用的是支持promises访问数据库的库,因此您应该在下一个.then方法中执行每个步骤。如果不执行.then方法中的步骤,则每个语句都在当前“tick”上执行,直到没有更多语句为“tick”。异步方法(使用db.none(...)调用)将在未来的“tick”上执行。这样您就可以看到最后2个console.log语句作为输出的第一个语句。

尝试将代码更改为类似下面的代码,以获得更好的工作流程:

'use strict';


// ================================================================================
// Module dependencies
var pgp      = require('pg-promise')();


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


// ================================================================================
// Initialise rhe variables
var customers = [];


// ================================================================================
// Initialise table
db.none("DELETE FROM testing")
  .then(function(data) {
    console.log("Deleted old records");
    // success;

    return db.none("INSERT INTO testing (firstname, surname) VALUES ('Bob', 'Brown')");
  })
  .then(function(data) {
    console.log("Inserted new record");
    // success;

    // Display records
    return db.any("SELECT * FROM testing");
  })
  .then(function(data) {
    console.log("Looping records");
    data.forEach(function(row, index, data) {
      customers.push(row.firstname, row.lastname);
      console.log(row);
    });
  })
  .then(function() {
    console.log("The customers are:");
    console.log(customers);
  })
  .catch(function(error) {
    console.log(error);
  });

了解每个操作/步骤在另一个.then方法中的效果。此外,由于db.方法返回promises,您可以返回.then方法中的那些方法,并且当该语句结束时将执行下一个.then

希望这有帮助。

答案 1 :(得分:1)

解决方案取决于查询之间是否存在依赖关系。如果他们是依赖的,你可以按照你的承诺链接他们;否则你可以批量并行执行它们:

'use strict';

var promise = require('bluebird');

var pgp = require('pg-promise')({
    promiseLib: promise // use a custom promise library
});

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

var db = pgp(config);

function prepareCustomers(t) {
    return t.batch([
        t.none('DELETE FROM testing'),
        t.none('INSERT INTO testing VALUES($1, $2)', ['Bob', 'Brown']),
        t.any('SELECT * FROM testing')
    ])
        .then(data=>data[2]); // get results from the select query
}

db.tx(prepareCustomers)
    .then(customers=> {
        console.log(customers);
    })
    .catch(error=> {
        console.log(error);
    })
    .finally(pgp.end); // only call pgp.end when exiting the application

此外,当你在这样的数据库中进行更改时,通常会使用一个事务,如上例所示。

  

有趣的是在"插入新记录"在重新命名命令提示符之前有30秒的等待时间。

请参阅Library de-initialization