我是使用Node js的新手,所以很可能我误解了“ promise”和“ callback hell”的概念。无论如何,我都需要有关如何避免以下代码的建议:
var Sequelize = require('sequelize');
var DB = new Sequelize('project1db', 'john', 'password123', {
host: 'localhost',
dialect: 'mysql'
});
var DB_PREFIX = 't_';
DB.query(
'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'user` ( ' +
'`user_id` int(11) UNSIGNED NOT NULL' +
') ENGINE=InnoDB DEFAULT CHARSET=utf8;',{type: DB.QueryTypes.RAW})
.then(function(results) {
DB.query(
'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'organization` ( ' +
'`organization_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT ' +
') ENGINE=InnoDB DEFAULT CHARSET=utf8; ', {type:DB.QueryTypes.RAW})
.then(function(results) {
DB.query(
'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'user_organization` ( ' +
'`user_id` int(11) UNSIGNED NOT NULL ' +
') ENGINE=InnoDB DEFAULT CHARSET=utf8; ')
.then(function(){
DB.query(
'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'content` ( ' +
'`content_id` int(11) UNSIGNED NOT NULL ' +
') ENGINE=InnoDB DEFAULT CHARSET=utf8; ', {type:DB.QueryTypes.RAW})
.then(function(){
// more queries
}).catch(function(err){console.log(err);});
}).catch(function(err){console.log(err);});
}).catch(function(err){console.log(err);});
}).catch(function(err){console.log(err);});
忽略了我用SQL创建表而不是使用Sequelize迁移脚本的事实,因为我只是想说明我有很多应该按顺序运行的mysql查询。如果查询失败,那么我需要停止整个脚本,而不要触发后续的.then()
函数。在我的Sequelize代码中,我通过嵌套许多原始查询函数调用,然后嵌套了catch语句来实现这一点。如果我有100个这些嵌套的回调语句,这将很难解决。
除了嵌套所有这些回调函数之外,我还有其他选择吗?
Sequelize使用bluebird
promises库(的修改版本),这意味着它应该起作用:
bluebird
[它使用var Promise = Sequelize.Promise;
Promise.each([
'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'user` ( ' +
'`user_id` int(11) UNSIGNED NOT NULL' +
') ENGINE=InnoDB DEFAULT CHARSET=utf8;',
'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'organization` ( ' +
'`organization_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT ' +
') ENGINE=InnoDB DEFAULT CHARSET=utf8; ',
'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'user_organization` ( ' +
'`user_id` int(11) UNSIGNED NOT NULL ' +
') ENGINE=InnoDB DEFAULT CHARSET=utf8; ',
'CREATE TABLE IF NOT EXISTS `'+DB_PREFIX+'content` ( ' +
'`content_id` int(11) UNSIGNED NOT NULL ' +
') ENGINE=InnoDB DEFAULT CHARSET=utf8; ',
], function runQuery(query) {
return DB.query(query, { type: DB.QueryTypes.RAW });
}).then(function() {
console.log('all done');
}).catch(function(err) {
console.log(err);
});
的静态版本,它将顺序地遍历数组项,将每个项传递给.each()
迭代器(返回承诺),并在拒绝承诺时停止。
您是否尚未通过不使用迁移脚本来回答自己的问题?默认情况下,您想运行迁移脚本来设置数据库并记录下来,以便您知道何时迁移或上次迁移。
如果需要顺序的SQL命令,您仍然可以在1个命令中执行。无论如何,查询将顺序运行。如果要使每个表都成为模型,请为该模型创建迁移脚本,不要这样做。
[为了避免出现“ promise hell”-与“ callback hell”一样的问题-可以将每个Promise都返回到顶层可扩展的库中:
.each()
Promise系统允许以这种方式链接,从而消除了对高级嵌套和缩进的需求。还要注意,只需要一个捕获-如果一个thenable失败,它将向前跳到下一个可用的runQuery
。