代码之家  ›  专栏  ›  技术社区  ›  leonheess

同步截击请求锁定

  •  1
  • leonheess  · 技术社区  · 7 年前

    我正在尝试实现“实时”输入验证。我现在面临的问题是如何实时检查数据库中是否已经存在用户名。

    对于所有的数据库请求,我都使用截击发布到PHP API,结果是:

    private boolean checkTaken(String username, Context context){
        boolean taken;
        Volley.getInstance(context).addToRequestQueue(new StringRequest(Request.Method.POST, url, output -> taken = output.contains("taken"), error -> {}) {
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<>();
                params.put("username", username);
                return params;
            }
            @Override
            public Map<String, String> getHeaders() {
                Map<String, String> params = new HashMap<>();
                params.put("Content-Type", "application/x-www-form-urlencoded");
                return params;
            }
        });
        return taken;
    }
    

    这很好,但不起作用,因为返回语句在API响应到达之前很久就到达了。就在那时,我发现了RequestFutures,并试图按照我所看到的实现它们 here

     private boolean checkTaken(String username, Context context){
    
        RequestFuture<String> taken = RequestFuture.newFuture();
    
        Volley.getInstance(context).addToRequestQueue(new StringRequest(Request.Method.POST, url, taken, error -> {}) {
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<>();
                params.put("username", username);
                return params;
            }
            @Override
            public Map<String, String> getHeaders() {
                Map<String, String> params = new HashMap<>();
                params.put("Content-Type", "application/x-www-form-urlencoded");
                return params;
            }
        });
        try {
            return taken.get(500, TimeUnit.MILLISECONDS).contains("taken");
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            return false;
        }
    }
    

    不幸的是,即使我将超时增加到无法忍受的程度,它也无法工作 taken.get() 永远无法解决。我想是因为 taken

    我将非常感谢你给我一个提示,为什么这不起作用,或者给我的问题提供另一个解决方案。

    方法调用:

    if (!email.matches(regex)){
        return "Username has an invalid format";
    } else if (checkTaken(username, context)){
        return "Username already taken";
    } else{
        return null;
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   nasch    7 年前
    private void checkTaken(String username, Context context, Callback callback){
        boolean taken;
        Volley.getInstance(context).addToRequestQueue(new StringRequest(Request.Method.POST, url, 
            output -> callback.done(output.contains("taken")), 
            error -> {
               // TODO handle this error
            }) {
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<>();
                params.put("username", username);
                return params;
            }
            @Override
            public Map<String, String> getHeaders() {
                Map<String, String> params = new HashMap<>();
                params.put("Content-Type", "application/x-www-form-urlencoded");
                return params;
            }
        });
    }
    

    定义回调接口并从调用的任何位置传入lambda表达式 checkTaken :

    // This method wherever this is defined also needs to accept a callback so it can be asynchronous
    public void whatever(StringCallback callback) {
        // ...
        if (!email.matches(regex)){
            callback.done("Username has an invalid format");
        } else {
            checkTaken(username, context, taken -> 
                     callback.done(taken ? "Username already taken" : null));
        } 
    

    whatever(error -> {
        if(error == null) {
            handleSuccess();
        }
        else {
            handleError(error);
        }
     );