javascript - 使用 Spring 3.2.0.RELEASE 的 DeferredResult 反向 ajax。无法在 IE 中工作

标签 javascript spring jquery spring-mvc spring-3

我正在尝试在 Spring 中使用反向 ajax 创建群聊演示。我使用的是 Spring 3.2.0.RELEASE 版本。

我正在使用 DeferredResult 在我的 Controller 中执行反向 ajax。以下是我的 Controller 类的片段。

@Autowired
private AsyncRepository asyncRepository;

Map<Integer, List<DeferredResult<String>>> watchers = new ConcurrentHashMap<Integer, List<DeferredResult<String>>>();

@RequestMapping(value="/asyncRequest/getMessages/{id}", method=RequestMethod.GET)
@ResponseBody
public DeferredResult<String> getMessages(final @PathVariable("id") Integer id){
    final DeferredResult<String> deferredResult = new DeferredResult<String>(null, Collections.emptyList());

    if(watchers.containsKey(id)) {
        watchers.get(id).add(deferredResult);
    } else {
        watchers.put(id, new ArrayList<DeferredResult<String>>());
        watchers.get(id).add(deferredResult);
    }

    deferredResult.onCompletion(new Runnable() {
        @Override
        public void run() {
            watchers.get(id).remove(deferredResult);
        }
    });

    return deferredResult;
}

@RequestMapping(value="/asyncRequest/setMessages/{id}/{message}", method=RequestMethod.GET)
@ResponseBody
public String setMessage(@PathVariable("id") Integer id, @PathVariable("message") String message) {
    asyncRepository.setMessage(id, message);

    return "";
}

@Scheduled(fixedRate=1000)
public void processQueues() {
    for (Map.Entry<Integer, Queue<AsyncDataBean>> entry : asyncRepository.getAsyncBeans().entrySet()) {
        while(entry != null && entry.getValue() != null && !entry.getValue().isEmpty()) {
            AsyncDataBean asyncDataBean = entry.getValue().poll();
            for (DeferredResult<String> deferredResult : watchers.get(asyncDataBean.getId())) {
                deferredResult.setResult(asyncDataBean.getMessage());
            }
        }
    }
}

下面是 Repository 类,它保存 GroupID 及其相关消息队列的 Map。它还具有获取和设置相关组ID的消息的功能。

@Repository
public class AsyncRepository {

    private Map<Integer, Queue<AsyncDataBean>> asyncBeans = new ConcurrentHashMap<Integer, Queue<AsyncDataBean>>();

    public String getMessages(Integer id) {
        StringBuilder stringBuilder = new StringBuilder();
        while (asyncBeans.get(id) != null && !asyncBeans.get(id).isEmpty()) {
            stringBuilder.append(asyncBeans.get(id).poll().getMessage()).append("~");
        }

        return stringBuilder.toString();
    }

    public void setMessage(Integer id, String message) {
        if(asyncBeans.containsKey(id)) {
            asyncBeans.get(id).add(new AsyncDataBean(id, message));
        } else {
            Queue<AsyncDataBean> messageQueue = new ConcurrentLinkedQueue<AsyncDataBean>();
            messageQueue.add(new AsyncDataBean(id, message));
            asyncBeans.put(id, messageQueue);
        }
    }

    public Map<Integer, Queue<AsyncDataBean>> getAsyncBeans() {
        return asyncBeans;
    }

    public void setAsyncBeans(Map<Integer, Queue<AsyncDataBean>> asyncBeans) {
        this.asyncBeans = asyncBeans;
    }
}

下面是我用来存储每条消息及其组 ID 的数据 bean。

public class AsyncDataBean {
    private Integer id;
    private String message;

    public AsyncDataBean() {
    }

    public AsyncDataBean(int id, String message) {
        this.setId(id);
        this.setMessage(message);
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

然后是群聊的jsp页面。如下所示。

<script type="text/javascript">
    var messagesWaiting = false;
    function getMessages(){
        if(!messagesWaiting){
            $.ajax({ url: "${pageContext.servletContext.contextPath}/asyncRequest/getMessages/${id}", 
                     dataType:"text",
                     success: function(data,textStatus,jqXHR) {
                         if(textStatus == 'success'){
                             messagesWaiting = false;
                             var arr = data.split("~");
                             for(var i=0; i<arr.length; i++)
                             {
                                    try
                                    {
                                        if(arr[i] != '') {
                                            $("#txtaMessages").val($("#txtaMessages").val() + "\n\n" + arr[i]);
                                            document.getElementById("txtaMessages").scrollTop = document.getElementById("txtaMessages").scrollHeight;
                                        }
                                    }
                                    catch(e){
                                     alert(e.message);
                                    }
                             }
                         }
                     }, 
                     complete: function(j) {
                     },
                     error: function(xhr) { 
                     }
            });
            messagesWaiting = true;
        }
    }
    setInterval(getMessages, 1000);
    getMessages();

    function sendMessage() {
        var xmlhttp1 = new XMLHttpRequest();
        xmlhttp1.open("GET", '${pageContext.servletContext.contextPath}/asyncRequest/setMessages/${id}/' + $("#txtMessage").val(), true);
        xmlhttp1.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        xmlhttp1.send();
        $("#txtMessage").val("");
        $("#txtMessage").focus();
    }
</script>

</head>
<body>
    <h1>Hello World!</h1>
    <table>
        <tr>
            <td>Messages :: </td>
            <td>
                <textarea cols="100" rows="10" id="txtaMessages"></textarea>
            </td>
        </tr>
        <tr>
            <td>Send Message :: </td>
            <td><input type="text" id="txtMessage"/></td>
        </tr>
        <tr>
            <td><input type="button" value="Send" onclick="sendMessage();"/></td>
        </tr>
    </table>
</body>
</html>

这就是我到目前为止所编写的代码,以使其正常工作。 FF 和 Chrome 中一切正常。但在 IE 中却没有按预期工作。该请求永远不会被服务器占用,并且总是按照 JavaScript 代码中的配置每秒执行一次。并且它总是返回与之前相同的结果。我尝试过使用其他几种方法向 IE 发送 ajax 请求,但它不起作用。有人可以让它为我工作吗?

由于在 FF 和 Chrome 中一切正常,我怀疑问题在于发送请求以获取消息的 javascript 代码。

请帮助我。

提前致谢。

最佳答案

这非常非常令人沮丧。

为了让这个东西在 IE 中正常工作,我需要在我使用 jquery for getMessages 创建的 ajax 请求中设置 cache:false 属性。否则,IE 不会将请求保持在待处理状态,并且始终返回旧的响应文本。

这是 IE 的一个非常大的问题。我希望没有人再次面临这个问题或尽早找到这个答案。

:)

关于javascript - 使用 Spring 3.2.0.RELEASE 的 DeferredResult 反向 ajax。无法在 IE 中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14376285/

相关文章:

javascript - 使用 JavaScript 更改行表颜色

java - Rail 的 'Gotchas' 和学习曲线 - 它会停止吗?

javascript - 在 JavaScript 中重定向而不丢失表单发布数据

java - 使用 Javascript 和 jOuery 访问 JSON 响应时出错

javascript - IE11 不加载大图像。说脚本 14 : not enough storage available to complete this operation

java - 通过组合来自两个类的字段创建 JSON

java - 通过 JMX 使 Spring 服务类可管理

javascript - 如何使 Accordion 事件项目可点击

jquery - 如果超过特定窗口大小,则交换 div 背景

javascript - react 大日历,将 Bootstrap 弹出窗口添加到事件?