循环阻止异步请求被发送。为什么以及如何解决?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了循环阻止异步请求被发送。为什么以及如何解决?相关的知识,希望对你有一定的参考价值。

我定义了如何处理我在匿名内部类中从服务器接收的响应,其中我将响应存储在Map中以允许从内部类外部进行访问。由于我的服务器调用是异步的,我实现了一个while循环来等待将结果放入映射,然后再将其返回给调用函数。但是,某种程度上我的循环没有被执行(据我所知至少),并且循环似乎阻止我的请求永远不会完成,这显然导致无限循环。

public Login getLoginByUsername(String username)
    {
        long callID = counter.incrementAndGet();
        System.out.println("Start call");
        ServerConnection.get("myURI",null, new JsonHttpResponseHandler(){
            @Override
            public void onSuccess(int statusCode, Header[] headers, JSONObject response){
                try {

                    System.out.println("Call success, enter result:");
                    callResults.put(callID, new CallResult(Login.parseFromJson(response)));
                    System.out.println(callResults.get(callID));

                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });

        System.out.println("start waiting");
       while(callResults.get(callID) == null){
            //wait
           System.out.print(".");
        }
        System.out.println("
waiting over, return result:");
        System.out.println(callResults.get(callID));
        return (Login) callResults.remove(callID).content;
}

我确信请求工作得很好。如果我删除循环(并返回null以避免NPE访问尚未完成的结果),我可以从控制台输出中看到请求已执行并在函数终止后生成有效结果。

我还尝试将整个请求(ServerConnection.get)移动到另一个方法,以防执行异步调用的方法由于某种原因必须终止以执行调用。这也没有帮助。

此外,我从来没有在循环中定义控制台输出,所以我怀疑它甚至执行得不错......

这里发生了什么,我该如何解决?

答案

while循环可能会最大化你的CPU并限制所有其他执行。在这样的等待循环中,你应该总是引入某种延迟,即使100-10ms也足够了。

只需在循环中调用Thread.sleep(100);(并在某处处理InterruptedException)。

例如:

   while(callResults.get(callID) == null){
       try {
           Thread.sleep(100);
       } catch (InterruptedException e) {
           return null; // Return null or just throw a RuntimeException. You can be pretty sure that this will never be called unless your app gets closed or your thread intentionally interrupted.
       }
       System.out.print(".");
    }
另一答案

由于相关的问题/问题更新代码(如果你很好奇,How to return response to calling function? (Android-App calling Java REST-Server via JSON)),我在我的请求中添加了一个主题:

public Login getLoginByUsername(String username)
    {
        long callID = counter.incrementAndGet();
        new Thread(new Runnable() {
            @Override
            public void run() {
                ServerConnection.get("person-login-relations?byUsername="+username,null, new JsonHttpResponseHandler(){
                    @Override
                    public void onSuccess(int statusCode, Header[] headers, JSONObject response){
                        try {
                            callResults.put(callID, new CallResult(Login.parseFromJson(response)));
                            System.out.println(callResults.get(callID));

                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                });


            }
        })   .start();

        while(callResults.get(callID) == null){
            //wait
        }
        return (Login) callResults.remove(callID).content;
    }

这似乎解决了我在这里描述的阻塞请求的循环的问题。我想这可能是因为请求或响应处理可能已由包含循环的同一线程处理,因此等待循环完成。我不完全确定,特别是因为我之前使用的是异步请求,它已在我控制之外的线程中处理

以上是关于循环阻止异步请求被发送。为什么以及如何解决?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 Ajax 发布请求在表单提交中被阻止?

循环,使用,以及如何阻止它

队列项结果返回给调用api调用的成员

当用ajax,弹窗向后台发送请求时,如何查看是否被中间件阻止?

如何在 node.js 中使用 axios 循环许多 http 请求

我如何知道浏览器通知是不是被 Windows 阻止