Last active
March 7, 2017 08:38
-
-
Save motss/5b0c1988bb426b59f74cc590347a3fae to your computer and use it in GitHub Desktop.
Long Polling with interval and max duration with ES6+
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Long polling happens in each successive `interval` and the long polling only allows to continue for `maxDuration`. | |
* `maxDuration` determines the time at which enough useful information has been gathered over the intervals, | |
* after all, things that too slow possess lesser significance by assumptions else they need to be improved | |
* if they are really important as no important/ high priority should load this slow. | |
* See [RAIL model](https://developers.google.com/web/fundamentals/performance/rail) for more info. | |
* | |
* Required parameters: | |
* 1. interval - how long the subsequent polling starts. | |
* 2. max duration - time reached to send out whatever has been gathered at that point. | |
*/ | |
let nPoll = 0; | |
let requestStarts = 0; | |
const responseComplete = 20E3; | |
const interval = 2E3; | |
const maxDuration = 10E3; | |
class LongPolling { | |
static init(fn, condition, interval, maximumInterval) { | |
let duration = 0; | |
const cachedInterval = typeof interval === 'number' ? interval : 2E3; | |
return new Promise((resolve, reject) => { | |
const check = () => { | |
Promise.resolve() | |
.then(fn) | |
.then(condition) | |
.then((val) => { | |
if (typeof val !== 'boolean') { | |
throw new TypeError('Expected condition to return a boolean'); | |
} | |
if (val === true || duration >= maximumInterval) { | |
resolve(); | |
} else { | |
setTimeout(check, cachedInterval); | |
duration += cachedInterval; | |
} | |
}) | |
.catch(reject); | |
}; | |
check(); | |
}); | |
} | |
} | |
poll = LongPolling.init; | |
let completed = {}; | |
(() => { | |
window.setTimeout(() => { | |
const requestEnds = window.performance.now(); | |
console.info(`completed at ${+new Date()} after ${(requestEnds - requestStarts) / 1000}s\n`); | |
completed = Object.assign({}, completed, { | |
status: 200, | |
message: 'completed', | |
}); | |
}, responseComplete); | |
})(); | |
poll( | |
async () => { | |
nPoll++; | |
if (completed.status === 200) return completed; | |
return await Promise.resolve().then(() => { | |
if (requestStarts < 1) requestStarts = window.performance.now(); | |
console.info(`${nPoll} - still in progress... ${+new Date()}\n`); | |
completed = Object.assign({}, completed, { status: 206, message: 'in-progress' }); | |
return completed | |
}); | |
}, | |
(data) => { | |
console.log('condition: ', data, data.status === 200); | |
return data.status === 200; | |
}, | |
interval, | |
maxDuration | |
) | |
.then(() => { | |
console.log('poll res:', completed); | |
}) | |
.catch(err => { | |
console.error('poll error:', err); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment