当响应是错误时,为啥承诺会进入 .then() ? - 拉拉维尔

Posted

技术标签:

【中文标题】当响应是错误时,为啥承诺会进入 .then() ? - 拉拉维尔【英文标题】:Why does promise go into the .then() when the response is an error? - Laravel当响应是错误时,为什么承诺会进入 .then() ? - 拉拉维尔 【发布时间】:2020-02-07 21:31:31 【问题描述】:

我正在使用 vue.js 和 vuex 和 vue 路由器在 Laravel 中制作 SPA。我在我的商店中进行了登录操作,但是当我使用无效凭据登录时,会发生一些非常奇怪的事情。当我使用正确的凭据登录时,它工作正常。

所以它调试以下内容

登录

app.js:279 发布http://127.0.0.1:8000/api/auth/login 401 (未经授权)

app.js:58018 登录成功

app.js:58023 登录失败

app.js:43201 未捕获(承诺) NavigationDuplicated _name: “NavigationDuplicated”,名称:“NavigationDuplicated”,消息: “不允许导航到当前位置(“/”)”,堆栈:“错误↵ 在新的 NavigationDuplicated (http://127....)↵ 在 http://127.0.0.1:8000/js/app.js:57159:12" 消息:“导航到 当前位置(“/”)不允许”名称:“NavigationDuplicated” _name:“NavigationDuplicated”堆栈:“错误↵ at new NavigationDuplicated (http://127.0.0.1:8000/js/app.js:43124:14)↵ at html5History.confirmTransition (http://127.0.0.1:8000/js/app.js:43240:18)↵ 在 HTML5History.transitionTo (http://127.0.0.1:8000/js/app.js:43184:8)↵ 在 HTML5History.push (http://127.0.0.1:8000/js/app.js:43515:10)↵ 在 http://127.0.0.1:8000/js/app.js:43929:22↵ 在新的承诺 ()↵ 在 VueRouter.push (http://127.0.0.1:8000/js/app.js:43928:12)↵ 在 http://127.0.0.1:8000/js/app.js:57159:12" 原型:错误

对我来说疯狂的是承诺进入 .then() 和 console.logs “登录成功”?它不应该进入 .then() 对吗?因为凭证是错误的,所以它应该只用于 .catch()。但更奇怪的是它确实调试了.then()中的第二个console.log(response.data)????我也不明白导航重复。

凭据只是一个用户名,密码。我正在使用 JWT,并且 /login 路由指向标准的 jwt authcontroller 登录方法。

Login.vue 组件方法

methods: 
    login() 
        this.$store
            .dispatch("tryLogin", this.form)
            .then(response => 
                this.$router.push( path: "/home" );
            )
            .catch(error => 
                this.logginError = error;
            );
    

商店操作

tryLogin(context, credentials) 
    context.commit("login");
    console.log("login");
    return new Promise((resolve, reject) => 
        axios
            .post("/api/auth/login", credentials)
            .then(response => 
                console.log("login succes");
                console.log(response.data);
                context.commit("loginSucces", response.data);
                resolve(response.data);
            )
            .catch(error => 
                console.log("login failed");
                context.commit("loginFailed", error);
                reject(error);
            );
    );

AuthController登录功能

/**
 * Get a JWT via given credentials.
 *
 * @return \Illuminate\Http\JsonResponse
 */
public function login()

    $credentials = request(['email', 'password']);

    if (!$token = auth('api')->attempt($credentials)) 
        return response()->json(['error' => 'Unauthorized'], 401);
    

    return $this->respondWithToken($token);

【问题讨论】:

检查您的网络请求,您确定服务器响应 401 吗? 是的,它正在响应 401 【参考方案1】:

好的,我会尝试解释(对不起我的英语)以下工作正常,当您使用错误的凭据登录时,它将返回一个很好的 JSON 响应:

 if (!$token = auth('api')->attempt($credentials)) 
        return response()->json(['error' => 'Unauthorized'], 401);
    

这不是失败,因此它进入.then并打印401 (Unauthorized) 然后它打印 console.log("login succes") ,然后当它尝试调用 context.commit("loginSucces", response.data);它失败了,然后会说app.js:58023登录失败。

您可以在.then 中询问来解决此问题

axios
    .post("/api/auth/login", credentials)
    .then(response => 
         if (response.data.status === "error") 
             console.log(response.data);
         
         else
             context.commit("loginSucces", response.data);
             resolve(response.data);
         
)

【讨论】:

我之前回答过这个问题,结果证明是错误的!试试这个,你会看到 我的问题是我必须在.then() 中进行错误捕获。我的 axios 拦截器是否有可能停止响应?这样 .then() 将永远不会运行? 另外,如果我检查 response.data.status 它会直接出错并进入 catch 因为 response.data 未定义。 ***.com/questions/50461746/… 这解决了我的问题

以上是关于当响应是错误时,为啥承诺会进入 .then() ? - 拉拉维尔的主要内容,如果未能解决你的问题,请参考以下文章

Firebase .orderByChild().equalTo().once().then() 当孩子不存在时承诺

.then()方法的意思和用法

打破承诺链 - 停止执行下一个“then”

Javascript 承诺在没有错误时捕获块启动

为啥一个已解决的承诺仍处于待处理状态?

ES6:解析包含其他 Promise 的 Promise,以便父级可以使用 .then