作为Javascript开发的一个相对开端,我试图理解我在我构建的函数中遇到的这个问题,它将成为连接到postgreSQL数据库的代码的一部分。
在这个函数中,我使用knex查询构建器方法来检查远程数据库中是否存在表,并且此方法解析为一个布尔值,指示您指定的字符串是否与同名的表匹配数据库。我提供了一个knex语法的示例,以便人们更好地理解该函数。
knex.schema.hasTable('users').then(function(exists) {
if (!exists) {
return knex.schema.createTable('users', function(t) {
t.increments('id').primary();
t.string('first_name', 100);
t.string('last_name', 100);
t.text('bio');
});
}
});
我试图让我的函数通过使用.every Array方法返回一个布尔值,该方法检查每个数组,并且每个索引都应该通过定义的条件,.every方法应该返回一个真值,否则返回false。我已经构建了一个函数,它接受一组模式键或表的名称,并将它传递给.every方法。然后.every方法使用knex.schema.hasTable方法返回true或false。
我担心的是,通过该功能的许多不同配置,我无法让它返回正确的值。它不仅会返回一个不正确的值,这可能与.every有关,我相信它可以返回“truthey”值,但是在定义函数之后,我会在以后调用它时经常遇到“函数未定义”错误文件。以下是我的功能示例 - 我认为这也是我对退货,承诺和关闭如何协同工作的理解不足,但如果有人有洞察力,那将非常感激。
var schemaTables = ['posts','users', 'misc'];
// should return Boolean
function checkTable() {
schemaTables.every(function(key) {
return dbInstance.schema.hasTable(key)
.then(function(exists) {
return exists;
});
});
}
console.log(checkTable(), 'checkTable function outside');
// console.log is returning undefined here, although in other situations,
I've seen it return true or false incorrectly.
答案 0 :(得分:2)
由于两个原因,您的功能无法正常运行:
checkTable
函数声明中返回,因此它将始终返回undefined。
你应该写:function checkTable() {
return schemaTables.every(function(key) {
return dbInstance.schema.hasTable(key)
.then(function(exists) {
return exists;
});
});
}
无论如何你不会得到你想要的东西只是添加回报。我将在第二点解释原因。
Array.prototype.every
期待一个真实或虚假的值同步但dbInstance.schema.hasTable
返回的是一个Promise对象(一个对象,即使是空的,也总是真实的)。 您现在要做的是检查表格是否存在异步,我将向您展示如何:
var Promise = require("bluebird");
var schemaTables = ['posts', 'users', 'misc'];
function checkTable(tables, callback) {
// I'm mapping every table into a Promise
asyncTables = tables.map(function(table) {
return dbInstance.schema.hasTable(table)
.then(function(exists) {
if (!exists)
return Promise.reject("The table does not exists");
return Promise.resolve("The table exists");
});
});
// If all the tables exist, Promise.all return a promise that is fulfilled
// when all the items in the array are fulfilled.
// If any promise in the array rejects, the returned promise
// is rejected with the rejection reason.
Promise.all(asyncTables)
.then(function(result) {
// i pass a TRUE value to the callback if all the tables exist,
// if not i'm passing FALSE
callback(result.isFulfilled());
});
}
checkTable(schemaTables, function (result) {
// here result will be true or false, you can do whatever you want
// inside the callback with result, but it will be called ASYNCHRONOUSLY
console.log(result);
});
请注意,正如我之前所说,你不能拥有一个同步返回true或false值的函数,所以你唯一能做的就是将回调函数传递给checkTable
,它将尽快执行因为结果准备好了(当所有承诺都履行或当其中一个承诺拒绝时)。
或者你可以return Promise.all(asyncTables)
then
checkTable
点击npm install express-generator -g
,但我会将此作为练习。
有关承诺的更多信息,请检查:
答案 1 :(得分:0)
感谢Cluk3提供了非常全面的答案。我实际上是通过在异步库中使用.every方法自己解决的。但是,是的,这主要是由于我对退货和异步与同步的误解。
var checkTablesExist = function () {
// make sure that all tables exist
function checkTable(key, done) {
dbInstance.schema.hasTable(key)
.then(function(exists) {
return done(exists);
});
}
async.every(schemaTables, checkTable,
function(result) {
return result;
});
};
console.log(checkTablesExist());
// will now print true or false correctly