gpt4 book ai didi

javascript - 从 Redis 返回数据仅在第二次有效

转载 作者:IT王子 更新时间:2023-10-29 06:05:24 26 4
gpt4 key购买 nike

我正在使用 Redis 数据库并为 API 快速路由。也使用 node.js 和 ioredis。

我连接到 Redis,然后获取与输入日期相关的所有键,然后获取与每个键相关的所有数据。

但令我感到奇怪的是,这一切都有效,但仅在第二次刷新请求它的页面时有效。因此,在第一次加载页面时(例如 blah.com/api/20120120),它将返回一个空数组。然后,如果您刷新页面,它将返回正确的数据。

HomeController.js:

var theData = [];

function getData (date) {
redis.on('ready', function (res) {
var keys = [];
var stream = redis.scanStream(
{
match: date + '*',
count: 1000
}
);
stream.on('data', function (resultKeys) {
for (var i = 0; i < resultKeys.length; i++) {
keys.push(resultKeys[i]);
}
});
stream.on('end', function () {
setValues(keys);
});
});
return theData;
}

var setValues = function(keys) {
for (var i = 0; i < keys.length; i++) {
redis.hgetall(keys[i], function (err, result) {
theData.push(result);
})
}
}

var HomeController = Controller.extend({

api: function (date) {
this.setRender();
this.getResponse().json(getData(date));
}

});

服务器.js:

app.get("/api/:date", router("HomeController", "api", ["date"]));

有人知道为什么会这样吗?

编辑:添加了 controller.js:

(function(module) {

"use strict";

// https://github.com/darlanalves/extends
var extend = require("extends");

var Class = function() {};

var Controller = extend(Class, {

constructor: function(req, resp) {
this._request = req;
this._response = resp;
this._view = null;
this._viewProperties = {};
this._render = true;

this.assign("loggedIn", false);
this.assign("location", req.protocol + '://' + req.get('host') + req.originalUrl);
},

assign: function(key, value) {
this._viewProperties[key] = value;
return this;
},

assignObject: function(obj) {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
this.assign(key, obj[key]);
}
}
},

failWith404: function() {
this.getRequest().log({status:404}, "controller 404");
this.getResponse().status(404).render('404.jade');
},

getRequest: function() {
return this._request;
},

getResponse: function() {
return this._response;
},

getView: function() {
return this._view;
},

getViewProperties: function() {
return this._viewProperties;
},

render: function() {
var viewProps = this.getViewProperties(),
logProps = {
loggedIn: viewProps.loggedIn,
};

if (this._render !== true) {
// No rendering, no headers
} else if (this.getView() !== null) {
// Jade
this.getResponse().render(this.getView(), this.getViewProperties());
} else {
// JSON response
this.getResponse().json(this.getViewProperties());
}

this.getRequest().log(logProps, "controller hit");
},

setRender: function(renderEnabled) {
this._render = (renderEnabled === true);
},

setView: function(viewName) {
this._view = viewName;
}

});

module.exports = Controller;

})(module);

最佳答案

你有一个异步的问题。

我还怀疑在每个后续请求中,您都会获得您在前一个请求中请求的数据。此外,如果您有多个用户,他们可能会收到其他人的请求。

关键问题:您的theData 超出了getData 函数的范围。另一个关键问题 - 你可以同步解决这个问题。

简化代码:

var theData = [];
function getData (date) {
redis.on('ready', handler);
return theData;
}

所以,首先调用算法:

  1. theData设置为[]
  2. 设置一些handler 来等待redis ready 事件。
  3. 返回theData(即[]);
  4. 稍后(当 redis 准备就绪时)您的处理程序将 theData 设置为结果。

第二次通话:

  1. 您不设置数据 - 仅在您的模块第一次加载时设置。意思是,theData 是您最后设置的值(这是来自上一个请求的数据,由 handler 设置。
  2. 再次安排 handlerready 事件上做一些事情。
  3. 返回 theData(现在保存着之前调用的数据)。
  4. 处理程序稍后会将数据设置为新数据。

等等等等

基本上,异步问题。

编辑:在您的示例代码更新后:

因此,随着您的代码更新,您必须执行如下操作:

getData 函数应该是异步的(返回 Promise 或使用回调)。还有你的 HomeController。

例子:

let HomeController = Controller.extend({

api: function (date) {
this.setRender();
getData(date) // Get data asynchroonously here
.then(function(data) {
this.getResponse().json(data);
})
.catch(function(err) {
// handle error
this.getResponse().status(500).json({message: 'Error getting data');
});
}
});

但是现在有一个问题 - getData 需要返回一个 Promise。

let Promise = require('bluebird'); //unless you have Node 0.12+, it has Promise already.
function getData(date) {


return new Promise(function(resolve, reject) {
let theData = []; // initialize empty data for each req
redis.on('ready', function() {

var keys = [];
var stream = redis.scanStream({
match: date + '*',
count: 1000
});
stream.on('data', function (resultKeys) {
for (var i = 0; i < resultKeys.length; i++) {
keys.push(resultKeys[i]);
}
});
stream.on('end', function () {
resolve(setValues(keys)); // Here we `resolve` our promise
});
stream.on('error', reject); // just a minor thing
}
});
}

但是现在您的 setValues 也需要异步,同样需要一个 Promise:

function setValues(keys) {

// Return a promise to the initial caller.
return new Promise(function(resolve, reject) {

let parallelizedQueries = keys.map(function(key) {

// Now, EACH of the hgetall also needs to be a Promise or somehow async
return new Promise(function(innerResolve, innerReject) {

redis.hgetall(key, function(err, result) {
if (err) {
return innerReject(err);
}
innerResolve(result);
});
});
});

// So now we have asked for each of the keys, in parallel.
// Wait until all of them succeed or fail on the first one.
Promise.all(parallelizedQueries)

.then(function(data) {

// Here is our data.
return resolve(data);
})
.catch(reject);
});
}

这应该让你开始了,希望你能从这里开始工作。

关于javascript - 从 Redis 返回数据仅在第二次有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35014743/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com