无法使用 NodeJS TypeScript 代码从 Redis 读取数据



我通过从客户端传递过滤器对象来调用名为 loadFilteredPolicy(( 的方法,该对象是我的哈希键,但它的方法 get(( 或 hgetall(( 永远不会被执行并且控制在没有从 Redis 服务器获取数据的情况下消失而不会引发任何错误。让我确认您可以调试并且可以确保 this.redisInstance 上有一个 redis 对象,但不确定为什么方法不执行。我可以通过命令hgetall直接使用 redis-cli 获取相同的数据。

我想告诉你的另一件事是,当我取消注释上面的承诺行(等待this.redisInstance.hgetall(并再次调试时,this.redisInstance返回undefined。我不确定发生了什么。我以前使用过JS,但打字稿不多,从早上开始我就陷入了这个错误,现在是晚上。

这是我的TypeScript代码(adapter.ts(,它被编译成JS文件:-

import { Helper, Model, FilteredAdapter } from 'casbin';
import * as redis from 'redis';
interface IConnectionOptions {
host: string;
port: number;
}
class Line {
ptype: string;
v0: string;
v1: string;
v2: string;
v3: string;
v4: string;
v5: string;
}
export class RedisAdapter implements FilteredAdapter {
private redisInstance = null;
private policies = null;
private filtered = false;
public isFiltered(): boolean {
return this.filtered;
}
private deliveredOptions = {
retry_strategy(options) {
if (options.error && options.error.code === 'ECONNREFUSED') {
return new Error('The server refused the connection');
}
if (options.total_retry_time > 1000 * 60 * 60) {
return new Error('Retry time exhausted');
}
if (options.attempt > 10) {
return undefined;
}
// reconnect after
return Math.min(options.attempt * 100, 300);
},
};
/**
* Helper Methods
*/
savePolicyLine(ptype, rule) {
const line = new Line();
line.ptype = ptype;
if (rule.length > 0) {
line.v0 = rule[0];
}
if (rule.length > 1) {
line.v1 = rule[1];
}
if (rule.length > 2) {
line.v2 = rule[2];
}
if (rule.length > 3) {
line.v3 = rule[3];
}
if (rule.length > 4) {
line.v4 = rule[4];
}
if (rule.length > 5) {
line.v5 = rule[5];
}
return line;
}
loadPolicyLine(line, model) {
console.log("load Policies line called");
let lineText = line.ptype;
if (line.v0) {
lineText += ", " + line.v0;
}
if (line.v1) {
lineText += ", " + line.v1;
}
if (line.v2) {
lineText += ", " + line.v2;
}
if (line.v3) {
lineText += ", " + line.v3;
}
if (line.v4) {
lineText += ", " + line.v4;
}
if (line.v5) {
lineText += ", " + line.v5;
}
Helper.loadPolicyLine(lineText, model);
}
storePolicies(policies) {
return new Promise((resolve, reject) => {
console.log({ r: this.redisInstance });
this.redisInstance.del('policies');
this.redisInstance.set('policies', JSON.stringify(policies), (err, reply) => {
if (err) {
reject(err);
} else {
resolve(reply);
}
});
});
}
reducePolicies(policies, ptype, rule) {
let i = rule.length;
let policyIndex = policies.fieldIndex((policy) => {
let flag = false;
flag = policy.ptype === ptype ? true : false;
flag = i > 5 && policy.v5 === rule[5] ? true : false;
flag = i > 4 && policy.v4 === rule[4] ? true : false;
flag = i > 3 && policy.v3 === rule[3] ? true : false;
flag = i > 2 && policy.v2 === rule[2] ? true : false;
flag = i > 1 && policy.v0 === rule[1] ? true : false;
return flag;
});
if (policyIndex !== -1) {
return policies.splice(policyIndex, 1);
}
return [];
}
constructor(options: IConnectionOptions) {
this.redisInstance = redis.createClient(
{
...options,
...this.deliveredOptions,
},
);
}
static async newAdapter(options: IConnectionOptions) {
const adapter = new RedisAdapter(options);
await new Promise(resolve => adapter.redisInstance.on('connect', resolve));
return adapter;
}
/**
* Adapter Methods
*/
public async loadPolicy(model) {
this.redisInstance.get("policies", (err, policies) => {
var AdapterRef = this;
console.log("Loading Policies...n", policies);
if (!err) {
policies = JSON.parse(policies);
this.policies = policies;//For add and remove policies methods
console.log(policies);
policies.forEach(function (policy, index) {
AdapterRef.loadPolicyLine(policy, model);
});
console.log("Policies are loaded");
} else {
return err;
}
});
}
public async loadFilteredPolicy(model: Model, filter: object): Promise<void> {
let key = filter['hashKey'];
//return await new Promise(function (resolve, reject) {
this.redisInstance.hgetall(key, (err, policies) => {
if (err) {
reject(err);
} else {
resolve(err);
var AdapterRef = this;
console.log("Loading filtered Policies...n", policies);
policies = JSON.parse(policies);
this.policies = policies;//For add and remove policies methods
console.log(policies);
policies.forEach(function (policy, index) {
AdapterRef.loadPolicyLine(policy, model);
});
console.log("Filtered Policies are loaded...");
this.filtered = true;
}
});
//})
}
public async savePolicy(model: Model): Promise<boolean> {
const policyRuleAST = model.model.get("p");
const groupingPolicyAST = model.model.get("g");
let policies = [];
//var rows2 = <Array<any>>policyRuleAST;
//var rows2 = <Array<any>>groupingPolicyAST;
for (const [ptype, ast] of Object.entries(policyRuleAST)) {
for (const rule of ast.policy) {
const line = this.savePolicyLine(ptype, rule);
policies.push(line);
}
}
for (const [ptype, ast] of Object.entries(groupingPolicyAST)) {
for (const rule of ast.policy) {
const line = this.savePolicyLine(ptype, rule);
policies.push(line);
}
}
//this.storePolicies(policies);
return new Promise((resolve, reject) => {
console.log({ r: this.redisInstance });
this.redisInstance.del('policies');
this.redisInstance.set('policies', JSON.stringify(policies), (err, reply) => {
if (err) {
reject(err);
} else {
resolve(true);
}
});
});
}
async addPolicy(sec, ptype, rule) {
const line = this.savePolicyLine(ptype, rule);
this.policies.push(line);
this.storePolicies(this.policies);
//reSave the policies
}
async removePolicy(sec, ptype, rule) {
let result = this.reducePolicies(this.policies, ptype, rule);
//the modified policies
if (result.length) { //if length>0
this.policies = result;
//Store in Redis
this.storePolicies(this.policies);
} else {
// console.IN("No Policy found");
throw new Error("No Policy Found");
}
}
public async removeFilteredPolicy(sec: string, ptype: string, fieldIndex: number, ...fieldValues: string[]) {
throw new Error("Method not implemented");
}
}

相应的适配器.js :-

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RedisAdapter = void 0;
const casbin_1 = require("casbin");
const redis = require("redis");
class Line {
}
class RedisAdapter {
constructor(options) {
this.redisInstance = null;
this.policies = null;
this.filtered = false;
this.deliveredOptions = {
retry_strategy(options) {
if (options.error && options.error.code === 'ECONNREFUSED') {
return new Error('The server refused the connection');
}
if (options.total_retry_time > 1000 * 60 * 60) {
return new Error('Retry time exhausted');
}
if (options.attempt > 10) {
return undefined;
}
return Math.min(options.attempt * 100, 300);
},
};
this.redisInstance = redis.createClient(Object.assign(Object.assign({}, options), this.deliveredOptions));
}
isFiltered() {
return this.filtered;
}
savePolicyLine(ptype, rule) {
const line = new Line();
line.ptype = ptype;
if (rule.length > 0) {
line.v0 = rule[0];
}
if (rule.length > 1) {
line.v1 = rule[1];
}
if (rule.length > 2) {
line.v2 = rule[2];
}
if (rule.length > 3) {
line.v3 = rule[3];
}
if (rule.length > 4) {
line.v4 = rule[4];
}
if (rule.length > 5) {
line.v5 = rule[5];
}
return line;
}
loadPolicyLine(line, model) {
console.log("load Policies line called");
let lineText = line.ptype;
if (line.v0) {
lineText += ", " + line.v0;
}
if (line.v1) {
lineText += ", " + line.v1;
}
if (line.v2) {
lineText += ", " + line.v2;
}
if (line.v3) {
lineText += ", " + line.v3;
}
if (line.v4) {
lineText += ", " + line.v4;
}
if (line.v5) {
lineText += ", " + line.v5;
}
casbin_1.Helper.loadPolicyLine(lineText, model);
}
storePolicies(policies) {
return new Promise((resolve, reject) => {
console.log({ r: this.redisInstance });
this.redisInstance.del('policies');
this.redisInstance.set('policies', JSON.stringify(policies), (err, reply) => {
if (err) {
reject(err);
}
else {
resolve(reply);
}
});
});
}
reducePolicies(policies, ptype, rule) {
let i = rule.length;
let policyIndex = policies.fieldIndex((policy) => {
let flag = false;
flag = policy.ptype === ptype ? true : false;
flag = i > 5 && policy.v5 === rule[5] ? true : false;
flag = i > 4 && policy.v4 === rule[4] ? true : false;
flag = i > 3 && policy.v3 === rule[3] ? true : false;
flag = i > 2 && policy.v2 === rule[2] ? true : false;
flag = i > 1 && policy.v0 === rule[1] ? true : false;
return flag;
});
if (policyIndex !== -1) {
return policies.splice(policyIndex, 1);
}
return [];
}
static async newAdapter(options) {
const adapter = new RedisAdapter(options);
await new Promise(resolve => adapter.redisInstance.on('connect', resolve));
return adapter;
}
async loadPolicy(model) {
this.redisInstance.get("policies", (err, policies) => {
var AdapterRef = this;
console.log("Loading Policies...n", policies);
if (!err) {
policies = JSON.parse(policies);
this.policies = policies;
console.log(policies);
policies.forEach(function (policy, index) {
AdapterRef.loadPolicyLine(policy, model);
});
console.log("Policies are loaded");
}
else {
return err;
}
});
}
async loadFilteredPolicy(model, filter) {
let key = filter['hashKey'];
//await new Promise(function (resolve, reject) {
await this.redisInstance.hgetall(key, (err, policies) => {
if (err) {
return err;
}
else {
var AdapterRef = this;
console.log("Loading filtered Policies...n", policies);
policies = JSON.parse(policies);
this.policies = policies;
console.log(policies);
policies.forEach(function (policy, index) {
AdapterRef.loadPolicyLine(policy, model);
});
console.log("Filtered Policies are loaded...");
this.filtered = true;
}
});
// });
}
async savePolicy(model) {
const policyRuleAST = model.model.get("p");
const groupingPolicyAST = model.model.get("g");
let policies = [];
for (const [ptype, ast] of Object.entries(policyRuleAST)) {
for (const rule of ast.policy) {
const line = this.savePolicyLine(ptype, rule);
policies.push(line);
}
}
for (const [ptype, ast] of Object.entries(groupingPolicyAST)) {
for (const rule of ast.policy) {
const line = this.savePolicyLine(ptype, rule);
policies.push(line);
}
}
return new Promise((resolve, reject) => {
console.log({ r: this.redisInstance });
this.redisInstance.del('policies');
this.redisInstance.set('policies', JSON.stringify(policies), (err, reply) => {
if (err) {
reject(err);
}
else {
resolve(true);
}
});
});
}
async addPolicy(sec, ptype, rule) {
const line = this.savePolicyLine(ptype, rule);
this.policies.push(line);
this.storePolicies(this.policies);
}
async removePolicy(sec, ptype, rule) {
let result = this.reducePolicies(this.policies, ptype, rule);
if (result.length) {
this.policies = result;
this.storePolicies(this.policies);
}
else {
throw new Error("No Policy Found");
}
}
async removeFilteredPolicy(sec, ptype, fieldIndex, ...fieldValues) {
throw new Error("Method not implemented");
}
}
exports.RedisAdapter = RedisAdapter;

如果您能建议我使此代码工作,我将不胜感激。我的此适配器源代码的 GitHub 链接可在此处获得 https://github.com/vinod827/node-casbin-redis-adapter.git

谢谢

[更新的代码,仍然无法正常工作]

async loadFilteredPolicy(model, filter) {
let key = filter['hashKey'];
let filteredPolicies = await this.getFilteredPolicies(key).then(data => { return data });
console.log(filteredPolicies);
}
getFilteredPolicies = async (hashKey) => {
return await new Promise(function (resolve, reject) {
this.redisInstance.hgetall((hashKey), function (err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
})
})
};

我认为你需要重新学习Promise的使用,至少你需要知道什么时候使用resolve()

请参阅:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

顺便说一句,不要以typescript为借口,只在这里javascript

我在这里为您提供一个有效的最小实现:

import * as redis from "redis";
const client = redis.createClient(6379, "127.0.0.1");
function func() {
return new Promise((resolve, reject) => {
client.hgetall("myhash", (err, data) => {
if (err) {
reject(err);
}
resolve(data);
});
});
}
async function main() {
const data = await func();
console.log(data);
}
main();

你能在 https://github.com/vinod827/node-casbin-redis-adapter/blob/master/src/adapter.ts#L150 上尝试下面的代码吗 ?

public async loadPolicy(model) {
return new Promise((resolve, reason)=> {
this.redisInstance.get("policies", (err, policies) => {
console.log("Loading Policies...n", policies);
if (!err) {
policies = JSON.parse(policies);
console.log(policies);
policies.forEach((policy, index)=> {
this.loadPolicyLine(policy, model);
});
console.log("Policies are loaded");
resolve()
} else {
reason(err)
}
});
})
}

最新更新