Javascript 函数使用了 promises 并且没有返回正确的值
Javascript function using promises and not returning the correct value
作为 Javascript 开发的相对开端,我试图理解我在构建的函数中遇到的这个问题,该函数将成为连接到 postgreSQL 数据库的代码的一部分.
在此函数中,我使用 knex 查询生成器方法检查远程数据库中是否存在 table,并且此方法解析为布尔值,指示您指定的字符串是否与table 数据库中的同名。我提供了一个 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 方法使我的函数 return 成为布尔值,该方法检查每个数组并且每个索引都应该通过定义的条件,.every 方法应该 return一个真值,否则为假。我构建了一个函数,该函数采用模式键数组或 table 的名称,并将其传递给 .every 方法。 .every 方法然后使用 knex.schema.hasTable 方法来 return 真或假。
我担心的是,通过函数的许多不同配置,我无法将其设置为 return 正确的值。不仅return取值不正确,可能跟.every有关系,我相信可以return "truthey"取值,而且定义函数后,经常会得到一个"Function undefined" 稍后在文件中调用它时出错。这是我的函数示例 - 我再次认为我对 returns、promises 和闭包如何协同工作的理解很差,但如果有人有见识,将不胜感激。
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.
您的功能无法正常工作有两个原因:
- 您没有在
checkTable
函数声明中 returning,因此它将始终 return 未定义。
你应该写:
function checkTable() {
return schemaTables.every(function(key) {
return dbInstance.schema.hasTable(key)
.then(function(exists) {
return exists;
});
});
}
无论如何你不会得到你想要的只是添加return。我会在第二点解释原因。
Array.prototype.every
期望一个真值或假值 syncronously 但 dbInstance.schema.hasTable
return 是一个 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);
});
请注意,正如我之前所说,您不能拥有同步 return 真值或假值的函数,因此您唯一能做的就是将回调传递给 checkTable
将在结果准备就绪后立即执行(当所有承诺都实现或其中一个拒绝时)。
或者您可以 return Promise.all(asyncTables)
并在 checkTable
上自行调用 then
,但我会把它留给您作为练习。
有关承诺的更多信息,请查看:
感谢 Cluk3 非常全面的回答。我实际上是通过使用 async 库中的 .every 方法自己解决的。但是,是的,这主要是由于我对 returns 和异步与同步的误解。
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
作为 Javascript 开发的相对开端,我试图理解我在构建的函数中遇到的这个问题,该函数将成为连接到 postgreSQL 数据库的代码的一部分.
在此函数中,我使用 knex 查询生成器方法检查远程数据库中是否存在 table,并且此方法解析为布尔值,指示您指定的字符串是否与table 数据库中的同名。我提供了一个 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 方法使我的函数 return 成为布尔值,该方法检查每个数组并且每个索引都应该通过定义的条件,.every 方法应该 return一个真值,否则为假。我构建了一个函数,该函数采用模式键数组或 table 的名称,并将其传递给 .every 方法。 .every 方法然后使用 knex.schema.hasTable 方法来 return 真或假。
我担心的是,通过函数的许多不同配置,我无法将其设置为 return 正确的值。不仅return取值不正确,可能跟.every有关系,我相信可以return "truthey"取值,而且定义函数后,经常会得到一个"Function undefined" 稍后在文件中调用它时出错。这是我的函数示例 - 我再次认为我对 returns、promises 和闭包如何协同工作的理解很差,但如果有人有见识,将不胜感激。
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.
您的功能无法正常工作有两个原因:
- 您没有在
checkTable
函数声明中 returning,因此它将始终 return 未定义。 你应该写:
function checkTable() {
return schemaTables.every(function(key) {
return dbInstance.schema.hasTable(key)
.then(function(exists) {
return exists;
});
});
}
无论如何你不会得到你想要的只是添加return。我会在第二点解释原因。
Array.prototype.every
期望一个真值或假值 syncronously 但dbInstance.schema.hasTable
return 是一个 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);
});
请注意,正如我之前所说,您不能拥有同步 return 真值或假值的函数,因此您唯一能做的就是将回调传递给 checkTable
将在结果准备就绪后立即执行(当所有承诺都实现或其中一个拒绝时)。
或者您可以 return Promise.all(asyncTables)
并在 checkTable
上自行调用 then
,但我会把它留给您作为练习。
有关承诺的更多信息,请查看:
感谢 Cluk3 非常全面的回答。我实际上是通过使用 async 库中的 .every 方法自己解决的。但是,是的,这主要是由于我对 returns 和异步与同步的误解。
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