JS承诺waitFor刷新令牌

时间:2017-08-04 02:52:41

标签: javascript node.js promise bluebird

情况很简单:

我有一个使用Bluebird作为Promise处理程序的nodejs服务器(称为API-A)。 我有一个客户端(浏览器)通过API-A询问数据,该API从另一个API(API-B)获取数据。 API-B可以是示例中的Weather服务,然后API-A将数据与其他数据聚合并将其发送回客户端。

情况如下:API-B需要一个TTL为1800秒的令牌。 因此,对于客户端完成的每个请求,我都会检查我的令牌是否已过期。

我有这样的代码:

function getActivities()
{
return this.requestAuthorisation()
       .then(()=>{
        // some other code that is not interesting
       })
}

一切都与诺言的荣耀一致。 requestAuthorisation()检查令牌是否有效(下一个!!!),如果没有(我请求API-B刷新令牌) 问题出在这里: 在时间,令牌过期和获得新鲜的时间之间,有时会发生。如果1000个客户同时询问这些,我将向API-B提出1000个令牌请求,这并不酷。

我该如何避免?我尽量避免使用cron方式,以避免不必要的调用,问题是一样的。

我尝试创建一种全局变量(boolean)来跟踪令牌的刷新状态但是找不到一种Promise.WaitFor(变量更改) Promise.all无法使用,因为我处于不同的事件范围内。

在令牌刷新之前有没有办法排队?

请帮忙!

1 个答案:

答案 0 :(得分:2)

如果我理解这篇文章,我们需要做两件事:

  • 当一个正在进行时,不要多次调用我们的refreshToken
  • 完成后,让所有等待请求知道已完成令牌的请求,以便他们可以继续工作。

如果将Observable模式和状态结合起来以维持正在进行的状态,可以像下面这样完成

MemTotal:       30946088 kB
MemFree:        11252496 kB
Buffers:          496376 kB
Cached:         11938144 kB
SwapCached:            0 kB
Active:         15023232 kB
Inactive:        3116316 kB
Active(anon):    5709860 kB
Inactive(anon):   394092 kB
Active(file):    9313372 kB
Inactive(file):  2722224 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:      15728636 kB
SwapFree:       15728636 kB
Dirty:               280 kB
Writeback:             0 kB
AnonPages:       5705052 kB
Mapped:           461876 kB
Shmem:            398936 kB
Slab:             803936 kB
SReclaimable:     692240 kB
SUnreclaim:       111696 kB
KernelStack:       33520 kB
PageTables:       342840 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:    31201680 kB
Committed_AS:   26896520 kB
VmallocTotal:   34359738367 kB
VmallocUsed:       73516 kB
VmallocChunk:   34359538628 kB
HardwareCorrupted:     0 kB
AnonHugePages:   2887680 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:        6132 kB
DirectMap2M:     2091008 kB
DirectMap1G:    29360128 kB

现在我们可以实现这个并观察完成的调用

// MyObservable.js:
var util = require('util');
var EventEmitter = require('events').EventEmitter;

let inProgress = false;

function MyObservable() {
  EventEmitter.call(this);
}
// This is the function responsible for getting a refresh token
MyObservable.prototype.getToken = function(token) {
  console.log('Inside getToken');
  if (!inProgress) {
    console.log('calling fetchToken');
    resultPromise = this.fetchToken();
    inProgress = true;
    resultPromise.then((result) => {
      console.log('Resolved fetch token');
      inProgress = false;
      this.emit('done', 'token refreshed');
    });
  }

}
// This is a mock function to simulate the promise based API.
MyObservable.prototype.fetchToken = function(token) {
  console.log('Inside fetchToken');
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('resolving');
      resolve("Completed");
    }, 2000);
  });
}

util.inherits(MyObservable, EventEmitter);
module.exports = MyObservable;

如果我们运行此代码,即使我们的方法const MyObservable = require('./MyObservable'); const observable = new MyObservable(); const A = () => { console.log('Inside A'); observable.on('done', (message) => { console.log('Completed A'); }); observable.getToken('test'); } for (let i = 0; i < 5; i++) { setTimeout(A, 1000); } 在相同的持续时间内被调用了5次,您将获得仅fetchToeken被调用一次的输出。

希望这有帮助!