1

I have an ES6 promise. I would like to use the promise to serialize API requests. There are interactive requests and background requests.

var apiPromise = Promise.resolve();

...
// Interactive requests
router.get('/apiRequest', (req,res) => {
  apiPromise.then(doSomeStuff)
  .then((results) => {
     res.send(results)
  })

...
// Background requests
setInterval(() => {
  if (apiPromise is resolved) {
    apiPromise.then(doSomeStuff)
  }
}, 1000*60)

I'd like to setInterval a function to .then() a queued request, only if the promise has been resolved. If it's not resolved, just wait to check at the next interval.

What's the best way to do that?

Update: Bluebird.js offers synchronous inspection: http://bluebirdjs.com/docs/api/isfulfilled.html

Michael Cole
  • 15,473
  • 7
  • 79
  • 96
  • Is there a reason why you can't continue the chain from within the middleware? – MinusFour Apr 04 '16 at 22:09
  • 3
    The closest you can get is a separate variable, e.g. `false` initially, set to `true` in `.then()`. The native `Promise` doesn't disclose its state in any manner beyond `.then()` and `.catch()`. – Jonathan Lonowski Apr 04 '16 at 22:10
  • 1
    This is not recommended as you disregard all the advantages of promises and make your program a polling client. – arisalexis Apr 04 '16 at 22:11
  • 2
    use a closured flag var that both "callbacks" can see, you can't tell by looking at the promise itself. – dandavis Apr 04 '16 at 22:13
  • 4
    This is just not how you use promises. You register for when they are resolved and you get called when they are resolved. You don't "poll" them on a timer. If you want to set your own flag when they are resolved, you can register a `.then()` handler and set your own flag. – jfriend00 Apr 04 '16 at 22:14
  • 3
    If you really need that interval, why not start it *after* the promise has resolved? – Mike Cluck Apr 04 '16 at 22:16
  • 1
    It sounds like what you actually want is `apiPromise.then(function(){ setInterval(doSomeStuff, 6e4); })` – Bergi Apr 04 '16 at 22:24
  • @JonathanLonowski: …and that's a good thing, sparing us from seeing more implementations like this one :-) – Bergi Apr 04 '16 at 22:25
  • 1
    It really depends on what you want out of this. I would look into something like [RxJS](http://reactivex.io/rxjs/manual/overview.html#introduction) if you are looking to do something even relatively complex with organization of async events over time. There's also other alternatives like [bacon.js](https://baconjs.github.io/) and [highland.js](http://highlandjs.org/) which I hear are similar. – John Apr 04 '16 at 22:30
  • @Bergi this isn't an "exact duplicate", because OP is using `setTimeout` so he obviously doesn't need inspection to be synchronous. Therefore I think [this answer](http://stackoverflow.com/a/35820220/918910) fits the bill. We don't know the whole context of the question, so lets not prejudge. – jib Apr 04 '16 at 23:55
  • @jib: It's `setInterval` not `setTimeout`, and the `if` itself is certainly synchronous. I'm pretty sure that it's a duplicate, even more if you consider the answer there to be applicable here. I dunno where "exact" came from, maybe SE changed the message once again. If the dupe and the comments don't help the OP, he should [edit] to provide the whole context, and we'll reopen. – Bergi Apr 05 '16 at 00:01
  • @Bergi my answer is a better fit to this question than the other one, and there's no reason the if needs to be synchronous. This works: `setInterval(() => promiseState(apiPromise).then(state => state == "fulfilled" && apiPromise.then(doSomeStuff)), 1000*60);` - deduct a millisecond from the interval if you wish :) – jib Apr 05 '16 at 00:04
  • If SO is changing the language to "exact duplicate" then I interpret that as a desire to narrow the use of marking as duplicate. – jib Apr 05 '16 at 00:07
  • @jib: What do you mean by "answer is better than the other one"? Both are answers to the duplicate question. – Bergi Apr 05 '16 at 01:29
  • @Bergi, I meant my answer is a better answer to this question than to the other question. – jib Apr 05 '16 at 01:36
  • Bluebird.js offers this: http://bluebirdjs.com/docs/api/isfulfilled.html – Michael Cole Apr 05 '16 at 15:34
  • The use case is very clear, from the OP's code. He wants to execute something every minute starting from when the promise resolves. The `promise.then(() => setInterval...` approach suggested in the comments does exactly that. There is no need whatsoever here (as there almost never is) for any synchonous inspection of the promise status, or any other @jib like machinery. On the duplicate issue, no-one will ever agree on the exact definition, but this certainly seems close enough, although it is true that the answers to that duplicate fail to clarify that this "requirement" is usually bogus. –  Apr 05 '16 at 17:09
  • @torazaburo I think you are misreading. The OP seems to want to only schedule background requests when idle (not processing any foreground requests). – jib Apr 05 '16 at 18:56

0 Answers0