2016-08-03 37 views
1

異步和掙扎的新手。正如下面我想初始化一個表的實例隨後處理它通過的內容: a)拆下舊數據 b)中插入一個新的記錄 c)讀取該表到一個數組 d)顯示陣列異步db編程的排序動作

'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的執行情形。

回答

1

由於您使用的庫支持訪問數據庫的承諾,因此您應該在接下來的.then方法中執行每一步。如果您不執行.then方法中的步驟,那麼每個語句都會在當前的「打勾」上執行,直到沒有更多的「打勾」語句爲止。該異步方法(稱爲與db.none(...)是在未來的「嘀」執行這個方式,你看最後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.方法返回的承諾,你可以返回那些.then方法和未來.then內將執行時語句執行完畢。

希望這有助於。

+0

非常好,謝謝你這麼多。我可以問:(a)在db語句允許它連接到下一個「.then」之前「返回」,而不是嵌套,這是我最初的期望? (b)爲什麼「db.none」會影響排序,我沒有得到那點意見。 (c)如果我想要插入兩條記錄而不是一條記錄,可以修改示例來顯示它。再次感謝。 – Dercni

+0

進一步思考。如果「.then」部分是異步操作完成後執行的部分,那麼這不是「回調」所做的。或者承諾回調的演變意味着不再需要使用回調。 – Dercni

+1

你也應該使用'task'或'tx'來針對相同的連接執行它。我會在幾個小時內發佈我的詳細答案,當我得到片刻。同時,請查看[Chaining Queries](https://github.com/vitaly-t/pg-promise/wiki/chaining-queries)。 –

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

+0

再次感謝你。我是否應該正確理解,關於應該被鏈接的例子應該被鏈接爲批處理會返回不可靠的結果,因爲舊的需要在插入新的元素之前被刪除,然後才能返回新的元素? – Dercni

+0

它似乎是一個批處理就像一個tx,唯一的區別是回滾的能力,所以當需要批處理時我總是可以使用tx。 – Dercni

+0

@ user1567212一方面,'批量'並行執行所有查詢。但是,它會針對相同的IO通道執行它們,從而將它們轉換爲同步序列。這就是交易完成的方式。所以它是可靠的。而且在更改數據時只應使用'tx',因此您需要回滾;否則使用'task'執行多個獨立的只讀查詢。 –