Вернуть топор ios обещание нескольким звонящим - PullRequest
0 голосов
/ 08 апреля 2020

Я сейчас создаю микросервис, используя Express. Чтобы получить токен доступа для второго микросервиса, я отправляю HTTP-запрос POST к конечной точке токена через ax ios. Чтобы уменьшить трафик c и упростить управление токенами, новый токен следует запрашивать только после истечения срока действия текущего токена. Если запрошен новый токен из-за истечения срока действия предыдущего, все абоненты должны подождать этот токен, а не запрашивать несколько новых токенов. Чтобы добиться этого, я реализовал следующий класс Auth, который создается как singleton:

class Auth {
   getToken() {
        if (this.token && !isExpired(this.token)) {
            return Promise.resolve(this.token);
        }
        if (!this.tokenPromise) {
            this.tokenPromise = axios
                .post(...)
                .then(response => {
                    console.log("received token");
                    this.tokenPromise = null;
                    this.token = response.data.token;
                    return response.data.token;
                })
                .catch(() => null);
        }
        return this.tokenPromise;
    }
}

// export Auth class as singleton
module.exports = new Auth();

Однако, когда я вызываю getToken, возвращаемое обещание никогда не разрешается, и оператор console.log("received token"); никогда не вызывается. В целях тестирования я изменил свой код и возвратил другое обещание вместо обещания топора ios:

class Auth {
   getToken() {
        if (this.token && !isExpired(this.token)) {
            return Promise.resolve(this.token);
        }
        if (!this.tokenPromise) {
            this.tokenPromise = axios
                .post(...)
                .then(response => {
                    console.log("received token");
                    this.tokenPromise = null;
                    this.token = response.data.token;
                    return response.data.token;
                })
                .catch(() => null);
            this.secondPromise = Promise.resolve("fakeToken");
        }
        return this.secondPromise;
    }
}

// export Auth class as singleton
module.exports = new Auth();

В этом случае возвращаемое обещание и обещание топора ios разрешаются при вызове getToken и console.log("received token"); называется. В чем причина этого и как я могу достичь желаемого поведения?

Минимальный рабочий пример

При создании этого минимального рабочего примера оказалось, что проблема происходит только при вызове метода getToken() из перехватчика ax ios (я следовал этим примерам при создании асинхронного c перехватчика). Вы можете воспроизвести проблему с помощью этого минимального рабочего примера:

mwe. js:

const axios = require("axios");

class Auth {
  getToken() {
    if (!this.tokenPromise) {
      console.log("get token");
      this.tokenPromise = axios
        .post("https://example.com")
        .then((response) => {
          console.log("received token");
          this.tokenPromise = null;
          return response;
        })
        .catch((err) => {
          console.log("err", err);
          this.tokenPromise = null;
          return null;
        });
    }
    return this.tokenPromise;
  }
}

const auth = new Auth();

axios.interceptors.request.use(
  async (config) => {
    const token = await auth.getToken();
    config.headers.Authorization = `Bearer ${token}`;
    return config;
  },
  (error) => {
    console.log("interceptor error", error);
  }
);

axios.get("https://example.com");

package. json:

{
  "name": "mwe",
  "version": "1.0.0",
  "description": "minimum working example",
  "main": "mwe.js",
  "scripts": {},
  "author": "",
  "license": "ISC",
  "dependencies": {
    "axios": "^0.19.2"
  }
}

При работе node mwe.js сообщение "get token" зарегистрировано, но не "received token".

...