首页 > 解决方案 > HTTP 调用由于另一个方法调用而被取消,如何强制阻止第二次调用,直到收到 HTTP 响应?

问题描述

我正在为 oauth2 做授权代码流,我在这里做错了,但我无法真正检测到..

这是我的代码

在 app.js 中

myService.setup().then(function(){...

在 service.js 中

var service = {
  setup(options) {
    this.processData();
    return this.getToken(options);
  },  

  processData(data) {
    let response = this._extractURLParams(window.location.href)
    if (response.hasOwnProperty("code")) {
      return this.handleAuthorizationCode(responseResult);
  },

  handleAuthorization(codeObject) {
  var service= this;
  return new Promise((resolve, reject) => {
    var xhr = new XMLHttpRequest();
    xhr.open("POST", /token, true);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    var params = 'grant_type=authorization_code&code=' + codeObject.code + '&client_id=client_id&client_secret=secret&redirect_uri=' + codeObject.redirectURi;

    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4 && xhr.status === 200) {
        var responseData = JSON.parse(this.response);
        resolve(service.storeToken(responseData));
      }
    };
    xhr.send(params);
  });
},

getToken(options) {
    let service = this;
    return new Promise(function (resolve, reject) {
   if(// localStorage has a token) {
     resolve(localStorage.getToken()) //dummy text, real code here
   } else {
      resolve(service.handleRedirectionsFlow(options));
      })
  },

发生的情况如下

1)当我访问我的应用程序时,我调用 myService.setup()

2)setup()方法会调用processData(),由于url为空,if条件不会通过,所以调用getToken()

3) getToken() 将调用一个方法,该方法将构建一个 url 并将位置更改为它,以便我们通过授权服务器上的表单进行身份验证,然后我们将在使用代码进行身份验证后重定向回应用程序!

4) 身份验证后,我们将重定向到应用程序,例如 'url?code=abcasdasdsfdasifsfsfs

5) 现在,processData() 将检测到 url 具有 code 属性,我们将调用 handleAuthorizationCode

6)handleAuthorizationCode 将简单地进行发布请求以获取令牌,并且 onReadyStateChange 我们将调用另一个方法来存储令牌。

7) 现在,当我们从 setup() 调用 getToken() 时,此时尚未从上一个方法触发 onreadystatechange,导致我们重做重定向以再次进行身份验证,然后令牌请求被取消并且我们从不存储它..

有人可以帮我知道我应该在哪里添加额外的承诺并解决它,以便在触发 onreadystatechange 并存储令牌以避免无限循环之后调用 getToken() 吗?

谢谢

标签: javascripthttp-post

解决方案


如果无法运行它很难知道,但是这个怎么样?

var service = {
    setup(options) {
        return this.processData()
            .then(token => token || this.getToken(options));
    },

    processData(data) {
        const response = this._extractURLParams(window.location.href);
        return response.hasOwnProperty("code")
            ? this.handleAuthorizationCode(responseResult)
            : Promise.resolve();
    },

    handleAuthorization(codeObject) {
        var service = this;
        return new Promise((resolve, reject) => {
            var xhr = new XMLHttpRequest();
            xhr.open("POST", /token, true);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            var params = 'grant_type=authorization_code&code=' + codeObject.code + '&client_id=client_id&client_secret=secret&redirect_uri=' + codeObject.redirectURi;

            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    var responseData = JSON.parse(this.response);
                    resolve(service.storeToken(responseData));
                }
            };
            xhr.send(params);
        });
    },

    getToken(options) {
        let service = this;
        return new Promise(function(resolve, reject) {
            if (localStorageHasToken) {
                resolve(localStorage.getToken()) //dummy text, real code here
            } else {
                resolve(service.handleRedirectionsFlow(options));
            }
        });
    }
};

本质上,我们processData总是返回一个 Promise,即使它是一个立即解决的 Promise,并且setup我们在调用之前等待processData()Promise 解决getToken

我不确定返回什么,但如果令牌已经存储service.storeToken(responseData),您可以使用它完全跳过调用。getToken


推荐阅读