由於Koa 1.x的核心抽象是在路由中使用控制流 的生成器,因此您必須使用yield
等待某件事完成。
興亞使用https://github.com/tj/co引擎蓋下,所以當試圖 互操作與沒有爲興亞建庫,作爲興亞開發人員,你 基本上只需要弄清楚如何修改/包異步庫 使你可以yield
他們在你的路線。
你可以基本yield
生成器和承諾。
這個工作最常用的工具是用 包裝一個函數Promise。在創建Promise(new Promise(fn)
)時,您必須將 函數fn
傳遞給函數和reject
。
您經常可以找到Co特定的庫,其中某人已經以允許您的yield
其功能/方法的方式包裝了一個受歡迎的 庫。
例如,檢查出https://www.npmjs.com/package/co-sqlite3。 (我不知道它有多好,但幸運的是,如果事實證明它不好,很容易自動換行)
或者,有些庫可以採用回調式模塊(即大多數Node模塊) 幷包裝它,使其返回承諾,您可以yield
。
例如,bluebird有一個promisifyAll函數可以做到這一點,儘管說實話我從來沒有用過藍鳥。
// (Untested)
var Promise = require('bluebird');
var sqlite3 = require('sqlite3').verbose();
var db = Promise.promisifyAll(new sqlite3.Database(':memory:'));
function* printMembers(name) {
var query = '...';
return yield db.allAsync(query, [name]);
}
function* index() {
// promisifyAll adds an {fnName}Async version of all the functions
// to the module you call it on, so now we can call `allAsync`.
var members = yield db.allAsync(query, ['name']);
// or
var members = yield printMembers('name');
this.body = members;
}
但我給你一些承諾,包裝的例子,因爲它是這樣一個基本 工具,在你的包。
在這裏我重寫printMembers
函數返回一個承諾,你 然後yield
從您的路徑:
var printMembers = function(name) {
var query = '...';
return new Promise(function(resolve, reject) {
var rows = [];
db.each(query, [name], function(err, row){
if (err) return reject(err);
rows.push(row);
});
resolve(rows);
});
}
雖然注意到sqlite3的有Database#all 功能,所有的行一次返回到你這麼您不必手動創建數組:
var printMembers = function(name) {
var query = '...';
return new Promise(function(resolve, reject) {
db.all(query, [name], function(err, rows){
if (err) return reject(err);
resolve(rows);
});
});
}
現在,這裏是你的路線是什麼樣子:
function *index() {
var members = yield printMembers('name');
this.body = members;
}
如果承諾打那reject(err)
路徑,然後承諾放於拒絕 狀態,將引發你可以try/catch語句,如果你想在這裏你產生 承諾的錯誤。
如果諾言命中resolve(members)
路徑,那麼這就是產生 並分配給members
變量。
哇,這是一個完美的答案! a)現在我知道JS的哪塊lego磚丟失了,b)您給出了多種解決方案,c)您甚至給出了一個工作示例。非常感謝!當你遇到問題時,它很難,但不知道要搜索什麼! – cvoigt