Write a class with a method getKey(key, callback) that invokes an API with the provided key. The method should also invoke a callback with the corresponding value returned by the API . Calls that are made within a given interval should be grouped.
Input:
getKey(v1/get?key=foo , ()=> console.log(x));
Output:
Let us assume the API returns the following
{foo: 50}
Then the callback is going to be invoked with corresponding value 50
// 50
API call with grouped keys, is used when the the subsequent calls are made within a 20 ms delay for example,
Input:
getKey(v1/get?key=foo , ()=> console.log(x)); // at t = 0
getKey(v1/get?key=bar , ()=> console.log(x)); // at t = 10
getKey(v1/get?key=foo , ()=> console.log(x)); // at t =20
Output:
Let us assume the API (domain/get?key=foo,bar,foo) returns the following
{foo: 50, bar: 100}
Then the callbacks are going to be invoked with the corresponding values 50, 100 and 50.
// 50
// 100
// 50
class Api { constructor(url, delay) { this.url = url + '?key='; this.delay = delay; this.queue = []; this.blocked = false; } getkey(key, cb) { this.queue.push([key, cb]); if (!this.blocked) { this.blocked = true; setTimeout(() => this.callApi(), this.delay) } } async callApi() { if (this.queue.length) { let keys = ''; const keyMap = {}; while (this.queue.length) { const [key, cb] = this.queue.shift(); keys = keys === '' ? key : keys + ',' + key; (keyMap[key] || (keyMap[key] = [])).push(cb); } try { const response = await fetch(this.url + keys); if (!response.ok) { throw 'Status: ' + response.status; } const data = await response.json(); // testing for data[data.args.key] = 12; for (const [key, val] of Object.entries(data)) { keyMap[key] && keyMap[key].forEach(cb => cb(val)); } } catch (e) { throw e; } this.callApi(); } else { this.blocked = false; } } } /* Test case */ const api = new Api('https://httpbin.org/get', 20) const test = (x) => console.log(x); api.getkey('foo', test)