- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我最初以为我无法让网络套接字
在 IE 11 下工作。现在,在添加大量调试细节后,我注意到套接字被正确调用。
问题是 IE 以某种方式返回旧数据。我注意到,在使用 IE 11 更新应用程序中的对象后,每当再次检索该对象时,它都不会获得最新的副本。 HTTP header 中的 ETag 设置为对象的原始版本而不是更新后的版本。
这是我的例子:
1) 进入申请主页面http://localhost:8081该页面默认加载用户页面。此页面将使用 ReactJS
从我的 Spring
应用程序加载 User
对象。
2) 更新用户的描述,从 UpdateNow
更改为 changed1
。
3) 这会触发更新,websocket 会更新数据库中的用户对象。
问题当我在 IE 中重新加载页面时,它会显示旧数据。即使关闭浏览器并打开新浏览器,它仍然会显示旧数据。启用 IE 调试时,我可以看到 header 中的 ETag 设置为原始版本而不是更新版本。
componentDidMount() {
log("calling componentDidMount");
this.loadFromServer(this.state.pageSize);
在 IE 中返回以下内容:
loadFromServer for type users
Opening Web Socket...
loadFromServer::: objectCollection:
[object Object]{entity: Object {...}, headers: Object {...}, raw: XMLHttpRequest {...}.....
loadFromServer::: objects:
这是第一个用户的对象数组中加载旧数据的位置:
firstName: Aaron
lastName: Smith
description: UpdateNow (this is old in the db it is currently set to changed1)
如果我们在 Chrome 中执行相同的操作,上述步骤是相同的,但我们会获取当前的 User 对象
description: "changed1"
firstName : "Aaron"
lastName : "Smith"
我可以进一步判断我的 IE 数据不正确,因为当我尝试对该用户进行更改时,当我对该用户执行 HTTP PUT 更新时,我会收到 412 前提条件失败状态代码,告诉我副本已过时。
问题2我可以为用户更新 Chrome 中的对象。当我这样做时,我可以看到 IE 在控制台中更新其对象版本,但它继续检索旧版本而不是新版本的对象。
问题
为什么 IE 会获取这些旧数据?看起来它以某种方式缓存在其中。我关闭了浏览器中的历史记录,删除了所有内容,甚至关闭并重新打开浏览器,但它不断检索旧数据。即使当我执行 CTRL-F5 时,它也会保留旧数据。
我注意到的另一件奇怪的事情是,我无法使用控制台调试从 IE 中看到网络主体请求/响应。尽管我在 http://localhost:8081/api/users/1 检索用户时可以看到 header 获得 HTTP 200,但它显示为 此资源没有响应负载数据
。我可以查看 header ,它们显示 ETag 对于使用原始 ETag(而不是新的 ETag)的 IE 来说已经过时了。
如果我在另一个客户端中查看请求和响应,它看起来很好。我想知道 IE 如何/为何以某种方式继续访问旧数据。
谢谢
代码/设置:
app.js
const stompClient = require('./websocket-listener');
.....(其他功能)
loadFromServer(pageSize, newObjectType) {
console.log("loadFromServer for type " + this.state.objectType);
var currentObjectType = this.state.objectType;
// check to see if we are refreshing the page for a new object type
if (newObjectType != null) {
log("setting new objectType of " + newObjectType);
// set the new object type for the page and refresh the results with that tyupe
currentObjectType = newObjectType;
}
follow(client, root, [
{rel: currentObjectType, params: {size: pageSize}}]
).then(objectCollection => {
console.log("loadFromServer::: objectCollection:")
console.log(objectCollection)
return client({
method: 'GET',
path: objectCollection.entity._links.profile.href,
headers: {'Accept': 'application/schema+json'}
}).then(schema => {
this.schema = schema.entity;
this.links = objectCollection.entity._links;
log("loadFromServer::: schema:")
log(schema)
return objectCollection;
});
}).then(objectCollection => {
this.page = objectCollection.entity.page;
log("loadFromServer::: objectCollection 2:")
log(objectCollection)
return this.getObjectMap(currentObjectType, objectCollection);
}).then(objectPromises => {
log("loadFromServer::: objectPromises:")
log(objectPromises)
return when.all(objectPromises);
}).done(objects => {
console.log("loadFromServer::: objects:")
console.log(objects)
this.setState({
page: this.page,
objects: objects,
attributes: Object.keys(this.schema.properties),
pageSize: pageSize,
links: this.links,
objectType: currentObjectType
});
});
}
componentDidMount() {
log("calling componentDidMount");
this.loadFromServer(this.state.pageSize);
// TODO add web socket callbacks for all entity types
stompClient.register([
{route: '/topic/newUser', callback: this.refreshAndGoToLastPage},
{route: '/topic/updateUser', callback: this.refreshCurrentPage},
{route: '/topic/deleteUser', callback: this.refreshCurrentPage},
{route: '/topic/newTestCase', callback: this.refreshAndGoToLastPage},
{route: '/topic/updateTestCase', callback: this.refreshCurrentPage},
{route: '/topic/deleteTestCase', callback: this.refreshCurrentPage},
{route: '/topic/newTestSuite', callback: this.refreshAndGoToLastPage},
{route: '/topic/updateTestSuite', callback: this.refreshCurrentPage},
{route: '/topic/deleteTestSuite', callback: this.refreshCurrentPage}
]);
}
客户端.js
'use strict';
var rest = require('rest');
var defaultRequest = require('rest/interceptor/defaultRequest');
var mime = require('rest/interceptor/mime');
var uriTemplateInterceptor = require('./api/uriTemplateInterceptor');
var errorCode = require('rest/interceptor/errorCode');
var baseRegistry = require('rest/mime/registry');
var registry = baseRegistry.child();
registry.register('text/uri-list', require('./api/uriListConverter'));
registry.register('application/hal+json', require('rest/mime/type/application/hal'));
module.exports = rest
.wrap(mime, { registry: registry })
.wrap(uriTemplateInterceptor)
.wrap(errorCode)
.wrap(defaultRequest, { headers: { 'Accept': 'application/hal+json' }});
网络套接字listner.js
'use strict';
var SockJS = require('sockjs-client'); // <1>
require('stompjs'); // <2>
function register(registrations) {
var socket = SockJS('/mcbserver'); // <3>
var stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
registrations.forEach(function (registration) { // <4>
stompClient.subscribe(registration.route, registration.callback);
});
});
}
module.exports.register = register;
package.json
"dependencies": {
"babel-core": "^6.8.0",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-2": "^6.5.0",
"react": "^15.0.1",
"react-dom": "^15.0.1",
"rest": "^1.3.2",
"sockjs-client": "^1.0.3",
"stompjs": "^2.3.3",
"webpack": "^1.13.0",
"when": "^3.7.7",
"react-bootstrap": "^0.29.3",
"jquery": "^2.2.3"
},
WebSocketConfiguration.java
`
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
@Component
@EnableWebSocketMessageBroker
public class WebSocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer {
static final String MESSAGE_PREFIX = "/topic";
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/mcbserver").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker(MESSAGE_PREFIX);
registry.setApplicationDestinationPrefixes("/app");
}
}
EventHandler.java
@Component
@RepositoryEventHandler(User.class)
public class EventHandler {
private final SimpMessagingTemplate websocket;
private final EntityLinks entityLinks;
@Autowired
public EventHandler(SimpMessagingTemplate websocket, EntityLinks entityLinks) {
this.websocket = websocket;
this.entityLinks = entityLinks;
}
@HandleAfterCreate
public void newUser(User user) {
this.websocket.convertAndSend(MESSAGE_PREFIX + "/newUser", getPath(user));
}
@HandleAfterDelete
public void deleteUser(User user) {
this.websocket.convertAndSend(MESSAGE_PREFIX + "/deleteUser", getPath(user));
}
@HandleAfterSave
public void updateUser(User user) {
this.websocket.convertAndSend(MESSAGE_PREFIX + "/updateUser", getPath(user));
}
@HandleAfterCreate
public void newTestCase(TestCase testCase) {
this.websocket.convertAndSend(MESSAGE_PREFIX + "/newTestCase", getPath(testCase));
}
@HandleAfterDelete
public void deleteTestCase(TestCase testCase) {
this.websocket.convertAndSend(MESSAGE_PREFIX + "/deleteTestCase", getPath(testCase));
}
@HandleAfterSave
public void updateTestCase(TestCase testCase) {
this.websocket.convertAndSend(MESSAGE_PREFIX + "/updateTestCase", getPath(testCase));
}
@HandleAfterCreate
public void newTestSuite(TestSuite testSuite) {
this.websocket.convertAndSend(MESSAGE_PREFIX + "/newTestSuite", getPath(testSuite));
}
@HandleAfterDelete
public void deleteTestSuite(TestSuite testSuite) {
this.websocket.convertAndSend(MESSAGE_PREFIX + "/deleteTestSuite", getPath(testSuite));
}
@HandleAfterSave
public void updateTestSuite(TestSuite testSuite) {
this.websocket.convertAndSend(MESSAGE_PREFIX + "/updateTestSuite", getPath(testSuite));
}
/**
* Take an {@link User} and get the URI using Spring Data REST's
* {@link EntityLinks}.
*
* @param user
*/
private String getPath(User user) {
return this.entityLinks.linkForSingleResource(user.getClass(), user.getId()).toUri().getPath();
}
/**
* Take an {@link TestCase} and get the URI using Spring Data REST's
* {@link EntityLinks}.
*
* @param user
*/
private String getPath(TestCase testCase) {
return this.entityLinks.linkForSingleResource(testCase.getClass(), testCase.getId()).toUri().getPath();
}
/**
* Take an {@link TestSuite} and get the URI using Spring Data REST's
* {@link EntityLinks}.
*
* @param user
*/
private String getPath(TestSuite testSuite) {
return this.entityLinks.linkForSingleResource(testSuite.getClass(), testSuite.getId()).toUri().getPath();
}
}
最佳答案
在 IE 11
中使用 F12
进行额外调试后,我实际上可以看到 IE
正在缓存每个 的详细信息HTTP GET
请求
。然后我找到了这个指南:
https://support.microsoft.com/en-ca/kb/234067
使用以下内容更新我的 Header
Requests
后,它工作正常。
'Pragma': 'no-cache', 'Expires': '-1', 'cache-control': 'no-cache'
关于javascript - IE 11 使用 Spring Boot/Spring Data REST 通过 ReactJS 中的 Stompjs 使用 Web 套接字检索旧版本的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37282766/
我想做的是让 JTextPane 在 JPanel 中占用尽可能多的空间。对于我使用的 UpdateInfoPanel: public class UpdateInfoPanel extends JP
我在 JPanel 中有一个 JTextArea,我想将其与 JScrollPane 一起使用。我正在使用 GridBagLayout。当我运行它时,框架似乎为 JScrollPane 腾出了空间,但
我想在 xcode 中实现以下功能。 我有一个 View Controller 。在这个 UIViewController 中,我有一个 UITabBar。它们下面是一个 UIView。将 UITab
有谁知道Firebird 2.5有没有类似于SQL中“STUFF”函数的功能? 我有一个包含父用户记录的表,另一个表包含与父相关的子用户记录。我希望能够提取用户拥有的“ROLES”的逗号分隔字符串,而
我想使用 JSON 作为 mirth channel 的输入和输出,例如详细信息保存在数据库中或创建 HL7 消息。 简而言之,输入为 JSON 解析它并输出为任何格式。 最佳答案 var objec
通常我会使用 R 并执行 merge.by,但这个文件似乎太大了,部门中的任何一台计算机都无法处理它! (任何从事遗传学工作的人的附加信息)本质上,插补似乎删除了 snp ID 的 rs 数字,我只剩
我有一个以前可能被问过的问题,但我很难找到正确的描述。我希望有人能帮助我。 在下面的代码中,我设置了varprice,我想添加javascript变量accu_id以通过rails在我的数据库中查找记
我有一个简单的 SVG 文件,在 Firefox 中可以正常查看 - 它的一些包装文本使用 foreignObject 包含一些 HTML - 文本包装在 div 中:
所以我正在为学校编写一个 Ruby 程序,如果某个值是 1 或 3,则将 bool 值更改为 true,如果是 0 或 2,则更改为 false。由于我有 Java 背景,所以我认为这段代码应该有效:
我做了什么: 我在这些账户之间创建了 VPC 对等连接 互联网网关也连接到每个 VPC 还配置了路由表(以允许来自双方的流量) 情况1: 当这两个 VPC 在同一个账户中时,我成功测试了从另一个 La
我有一个名为 contacts 的表: user_id contact_id 10294 10295 10294 10293 10293 10294 102
我正在使用 Magento 中的新模板。为避免重复代码,我想为每个产品预览使用相同的子模板。 特别是我做了这样一个展示: $products = Mage::getModel('catalog/pro
“for”是否总是检查协议(protocol)中定义的每个函数中第一个参数的类型? 编辑(改写): 当协议(protocol)方法只有一个参数时,根据该单个参数的类型(直接或任意)找到实现。当协议(p
我想从我的 PHP 代码中调用 JavaScript 函数。我通过使用以下方法实现了这一点: echo ' drawChart($id); '; 这工作正常,但我想从我的 PHP 代码中获取数据,我使
这个问题已经有答案了: Event binding on dynamically created elements? (23 个回答) 已关闭 5 年前。 我有一个动态表单,我想在其中附加一些其他 h
我正在尝试找到一种解决方案,以在 componentDidMount 中的映射项上使用 setState。 我正在使用 GraphQL连同 Gatsby返回许多 data 项目,但要求在特定的 pat
我在 ScrollView 中有一个 View 。只要用户按住该 View ,我想每 80 毫秒调用一次方法。这是我已经实现的: final Runnable vibrate = new Runnab
我用 jni 开发了一个 android 应用程序。我在 GetStringUTFChars 的 dvmDecodeIndirectRef 中得到了一个 dvmabort。我只中止了一次。 为什么会这
当我到达我的 Activity 时,我调用 FragmentPagerAdapter 来处理我的不同选项卡。在我的一个选项卡中,我想显示一个 RecyclerView,但他从未出现过,有了断点,我看到
当我按下 Activity 中的按钮时,会弹出一个 DialogFragment。在对话框 fragment 中,有一个看起来像普通 ListView 的 RecyclerView。 我想要的行为是当
我是一名优秀的程序员,十分优秀!