从 $http.error 事件返回 $q.reject 的问题

Issues returning $q.reject from an $http.error event

我有一个登录页面,它将用户凭据提交给登录控制器。 但是在授权用户之前,我需要 "open" 一个会话并接收一个有效的 sessionID。

然而,我的主要问题是处理下方 this.openUserSession API 调用的错误事件。也就是说,我在 $http.error() 事件上 returning 一个 $q.reject(),但它并没有像我预期的那样冒泡堆栈。

流程如下:

1) 用户输入凭据并单击 "Login" 按钮,调用 LoginCtrl 函数 loginUser()

2) 我立即调用 ing userService.initUserSession 以获得有效的 sessionID。

3) 如果成功,则调用loginService.authUser 4)如果无效的sessionID,那么我需要return$q.reject并显示消息 "Could not open user session"

***** 代码详细信息 *****

请注意,我首先 "init" that.initRzr 中的应用程序,然后我在下面调用 that.openUserSession

this.initUserSession = function initSession($rootScope, username) {    

var deferred = $q.defer();
deferred.notify("Establishing Session ID...");

$rootScope.userID = username;
var that = this;
this.getRazorInitParams().then(function (razorEnvJson) {
 
 that.initRzr(razorEnvJson).then(function (data) {
  
  if (data.status.match(/SUCCESS/g)) {
   
   // ******** OPEN USER SESSION ***********
   that.openUserSession(razorEnvJson).then(function (data) {
    // ... some code omitted here.
    deferred.resolve(sessionID);
    return sessionID;
   });
  }
 }, function (error) {
               // *** I NEVER HIT LINE !!! ***
  deferred.reject('Could not open user session.');
 });
});
return deferred.promise;
}

**** 打开用户会话 ***

注意:我在这里输入 .error() 代码,因为我可以看到控制台记录的消息 "Cannot open a user session via api cal..."。但是,处理似乎就此停止,我的登录屏幕只是冻结并显示微调器图标。

this.openUserSession = function (razorEnvParams) {
    
 // init some variables here...
 
 var url = "http://" + _domain + ":" + _port + controllerpath + "?userid=" + user + "&pass=" + pass;
 var deferred = $q.defer();
 deferred.notify("Opening user session..."); 
 
 $http({
  method: 'GET',
  encoding: 'JSON',
  headers: {
   'Access-Control-Allow-Origin': 'true',
   'Content-Type': 'application/json'
  },
  withCredentials: true,
  url: url
 }).success(function (data, status, headers, config) {  
  deferred.resolve(data);
 }).error(function (data, status, headers, config) {
  console.log("Cannot open a user session via api call. Errors details: " + data);
  deferred.reject("Could not open a user session.");
 });
 return deferred.promise;
}

如果不清楚,我会尽力改进post。请指教...

提前致谢。

鲍勃

**** 更新 ****

根据下面 JB Nizet 的回答,我错过了 that.openUserSession 的错误回调。我在下面添加了 function(error),它按预期工作。

我现在将继续 JB posted 的链接建议。

this.initUserSession = function initSession($rootScope, username) {       // ESTABLISH A RAGE CONNECTION AND SESSION ID !

var deferred = $q.defer();
deferred.notify("Establishing Rage Session ID...");

var that = this;
this.getRazorInitParams().then(function (razorEnvJson) {

 that.initRazor(razorEnvJson).then(function (data) {
  
  if (data.status.match(/SUCCESS/g)) {
   that.openUserSession(razorEnvJson).then(function (data) {
    
    deferred.resolve(sessionID);
    return sessionID;
   }, function (error) {
    deferred.reject('Could not open user session.');
   });
  }
 }, function (error) {   // **** ADDED ERROR HANDLING ***
  deferred.reject('Could not initial a user session.');
 });
});
return deferred.promise;
}

openUserSession() 失败,并且您没有针对该失败的任何错误回调,因此承诺永远不会被解决或拒绝。

此错误和大的叠瓦是由您使用 promise antipattern 引起的。改为使用链接:

that.getRazorInitParams()
    .then(that.initRzr)
    .then(that.openUserSession)
    .catch(function() { ... });

无需创建延迟和解析它。只需使用链接。例如,openUserSession() 可以替换为

this.openUserSession = function (razorEnvParams) {

    var url = "http://" + _domain + ":" + _port + controllerpath;
    return $http({
        method: 'POST',
        encoding: 'JSON',
        headers: {
            'Access-Control-Allow-Origin': 'true',
            'Content-Type': 'application/json'
        },
        withCredentials: true,
        url: url,
        params: {
            userid: user,
            pass: pass
        }
    }).then(function (response) {       
        return response.data;
    });
}

此外,永远不要使用 GET 来传输秘密凭据:它们最终会以纯文本形式出现在各种日志中。永远不要连接参数。它们必须经过编码,Angular 通过使用 params.

为您完成编码