ApolloClient timeout best option - javascript

I came up with this way of doing network operations with ApolloClient but the problem is that the code looks very ugly and difficult to read, considering I have to write dozens of queries like this, it becomes tiresome and unmaintainable.
I haven't found anything in the Apollo docs or the actual code to configure the timeout.
let query = gql`
query ... {
}`;
let x = 0;
let timer = setTimeout(() => {
if (x === 0) {
console.log('error');
}
x = 1;
}, 3000);
ApolloClient.query({ query }).then(({data}) => {
clearTimeout(timer);
if (x === 0) {
if (data.result) {
console.log(data.result)
} else {
console.log('error');
}
}
}).catch((error) => {
clearTimeout(timer);
console.log('error')
});
Is there a better way of achieving the same result with less and simpler code?

Turns out, you can override the method:
export async function query(request) {
const options = {...this._opts};
return new Promise((resolve, reject) => {
setTimeout(() => reject('Network timed out'), 1e4); // 10 sec
return this.applyMiddlewares({
request,
options
}).then((rao) => {
return this.fetchFromRemoteEndpoint.call(this, rao);
}).then(response => this.applyAfterwares({
response: response,
options
})).then(({response}) => (response).json()).then((payload) => {
resolve(payload);
}).catch((e) => {
reject(e);
});
}).catch((e) => {
console.log(e);
return null;
});
}

Related

How can I retry a function with try/catch promise in react js?

I need help with a performative way to retry if the return is 500, to try again
What would be the most viable solution in this case?
useEffect(() => {
setCSV(createPayload())
;(async () => {
try {
setIsLoadingGraph(true)
const response = await api.generateDataByFilters(createPayload())
response.data.itens.forEach((data) => {
setDataTable(data.detail)
setDataGraph(data.summarizedBySenderNumber)
setTotalDispatchMessages(data.totalDispatchMessages)
setTotalSentMessages(data.totalSentMessages)
setTotalReceivedMessages(data.totalReceivedMessages)
setTotalReadMessages(data.totalReadMessages)
setTotalFailedMessages(data.totalFailedMessages)
setTotalBillableMessages(data.totalBillableMessages)
})
setIsLoadingGraph(false)
} catch (error) {
console.error(error)
}
})()
}, [periodFilter, originFilter, senderFilter, endDateTime, initialDateTime])
Just give the function a name, then in the catch method, if the status === 500, re-execute the function again, Also you can give a throttling between each request by for example 2 seconds.
useEffect(() => {
setCSV(createPayload())
const generateDataByFilters = async () => {
try {
setIsLoadingGraph(true)
const response = await api.generateDataByFilters(createPayload())
response.data.itens.forEach((data) => {
setDataTable(data.detail)
setDataGraph(data.summarizedBySenderNumber)
setTotalDispatchMessages(data.totalDispatchMessages)
setTotalSentMessages(data.totalSentMessages)
setTotalReceivedMessages(data.totalReceivedMessages)
setTotalReadMessages(data.totalReadMessages)
setTotalFailedMessages(data.totalFailedMessages)
setTotalBillableMessages(data.totalBillableMessages)
})
setIsLoadingGraph(false)
} catch (error) {
console.error(error)
if (error.status === 500) {
await new Promise((resolve, reject) => {
setTimeout(() => {
generateDataByFilters()
resolve()
}, 2000)
})
}
}
}
}, [periodFilter, originFilter, senderFilter, endDateTime, initialDateTime])

how to call second API after first API result is retrieved

I have a API which called the bank end :
this.http.get(`http://localhost:44301/consentinitiation/${this.qid}`)
.pipe(retryWhen(_ => {
this.showIt=true
return interval(1000)
}))
.subscribe(result => {result
console.log(result);
this.qrcodelink=result["qrCodeLink"];
setTimeout(() => {
this.loadingSpinner=false;
}, 5000);
})
It has a result and has a status which is "Recieved" after that i should call the API again unstil i get the status "Finalized" and dont how to call the API again ,after the first call is finished,because if i write it below the first one i guess they will call the simultaneously,any idea?
the problem that u describe in description is called polling ( make request in interval until u got an expected result )
here is poll implementation in rxjs way
makeSomeRequestsToBank() {
this.http.get('https://').pipe(
switchMap(result => {
// if status is recieved, start polling
if (result.status === 'Recieved') {
return this.pollStatus();
}
if (result.status === 'Finalized') {
return of(result)
}
// else do some thing else, depends on u business logic
// keep in mind that switchMap should return an observable for futher chaining
return of(undefined);
}),
).subscribe(result => {
if (!result) return;
this.qrcodelink=result["qrCodeLink"];
setTimeout(() => {
this.loadingSpinner=false;
}, 5000);
}
pollStatus(): Observable<any> {
const POLLING_INTERVAL = 700; // poll in ms
const isSuccessFn = (response: string) => response === 'Finalized'; // the condition to stop polling and return result
return timer(0, POLLING_INTERVAL).pipe(
switchMap(() => this.http.get('https://')),
skipWhile(response => isSuccessFn(response)),
);
}
You can do it with using Promise.
ngOnInit(){
this.callFirstApi();
}
firstApi(): Promise<any> {
return new Promise((resolve, reject) => {
this.http.get(API_URL).subscribe((data) => {
resolve(data);
}, (error) => {
reject(error);
});
});
}
secApi(): Promise<any> {
return new Promise((resolve, reject) => {
this.http.get(API_URL).subscribe((data) => {
resolve(data);
}, (error) => {
reject(error);
});
});
}
callFirstApi(){
this.firstApi().then(response => {
this.callSecApi();
}).catch(err => {
})
}
callSecApi(){
this.secApi().then(response => {
}).catch(err => {
})
}

After post request, continue checking for completion | Node.js

I'm making a post request with a good amount of data that will take about a minute to finish saving. The hosting service I'm using for this will time out requests after 5 seconds, so I need to set this up to periodically check if the data saving is complete to give a final update.
I'm using request-promise, and have looked at both setTimeout and setInterval approaches. In my latest attempt (below) I'm using a setTimeout approach, but my second then keeps being called pretty much immediately. I want this to hang out in the first then stage until it's checked a bunch of times (24 here) or actually finished.
I might have a totally wrong approach here, but I'm not finding examples of the thing I'm trying to reference. Any direction to a good example of this or where I'm going wrong would be greatly appreciated.
const request = require('request-promise');
function checkFiles () {
return request({
uri: `${process.env.ROOT_URL}/api/v1/get/file-processing`,
method: 'GET',
json: true
})
.then(res => { return res; })
.catch(err => { return err; });
}
async function init () {
const filesPostOptions = {/* request options */};
await request(filesPostOptions)
.then(async status => { // THEN #1
if (status.status === 201) {
return status;
}
let checks = 0;
const checkIt = function() {
checks++;
checkFiles()
.then(res => {
if (res.status === 201 || checks > 24) {
status = res;
return status;
} else {
setTimeout(checkIt, 5000);
}
})
.catch(err => {
console.error(err);
});
};
checkIt();
})
.then(status => { // THEN #2
if (!status.status) {
throw Error('Post request timed out.');
}
return status;
})
.catch(err => {
err = err.error ? err.error : err;
console.error(err);
});
}
The post response will deliver a response with a status property (the status code) and a message property.
You need to control the return in "THEN #" by adding a Promise:
.then(async status => { // THEN #1
return new Promise((resolve, reject) => { // <---- prevent an immediate return
if (status.status === 201) {
return resolve(status);
}
let checks = 0;
const checkIt = function() {
checks++;
checkFiles()
.then(res => {
if (res.status === 201 || checks > 24) {
status = res;
resolve(status);
} else {
setTimeout(checkIt, 1000);
}
})
.catch(err => reject(err));
};
checkIt();
})
})

async issues with js generator and promises not returning result

I'm having yet another async issue where I'm lost and have no idea where or how to fix it. Forgive my bad naming.
api call to twitch api and returns an array its results.
exports.batchPromiseWrapper = function(arr) {
const filteredMungedDataArr = [];
let promiseBatachArray = arr.map(vod_id => {
var url = `https://api.twitch.tv/kraken/videos/${vod_id.id}/markers`;
var params = { api_version: 5 };
return axios
.get(url, {
params: params,
headers: {
"Client-ID": "xxxxxxxxxxxxxxx"
}
})
.then(res => {
return res.data;
})
.catch(function(error) {
console.log(error);
});
});
return Promise.all(promiseBatachArray)
.then(markers => {
if (markers !== null) {
markers.map(markerObj => {
if (markerObj.markers.game_changes !== null) {
markerObj.markers.game_changes.forEach(gameName => {
if (gameName.label === "Fortnite") {
filteredMungedDataArr.push(markerObj);
}
});
}
});
return filteredMungedDataArr;
}
})
.catch(err => {
if (err.status === 500 || err.status === 404) {
console.log("error: ", err, err.message);
}
});
};
The data looks like this:
[[1,2,3,4,5],[1,2,3,4,5]], generator will yield and make a promise.all call of 5 before pausing 5sec and continuing to the next batch of 5.
exports.batchFetchingGeneratorWrapper = function(generator, batchArray) {
let evalNextValue = generator.next();
let delay = (v, t) => {
return new Promise(resolve => {
setTimeout(resolve.bind(null, v), t);
});
};
if (!evalNextValue.done) {
exports.batchPromiseWrapper(evalNextValue.value).then(data => {
let newBatchArray = batchArray;
if (data !== undefined) {
newBatchArray = batchArray.concat(data);
}
delay(5000).then(() => {
exports.batchFetchingGeneratorWrapper(generator, newBatchArray);
});
});
} else {
console.log("yay done!", batchArray);
return batchArray;
}
};
I'm able to console the results in batchArray from batchFetchingGeneratorWrapper, but I unable to act on it and I know it has something to do with async and how it has yet to be resolved.
promiseDataWrapper
.then(data => {
return gatherData.cleanUpVODData(data);
})
.then(data => {
function* batchFetching(batchArray) {
for (let i = 0; i < batchArray.length; i++) {
yield batchArray[i];
}
}
let batchArrResult = [];
let g = batchFetching(data);
new Promise((resolve, reject) => {
gatherData.batchFetchingGeneratorWrapper(g, batchArrResult);
if (g.done) { // i dont think this works
console.log("batchArrResult 1: ", batchArrResult);
resolve(batchArrResult);
}
}).then(result => console.log("asdfasdf", batchArrResult)); // empty array is returned
});
As far as I can tell, the problem lies chiefly in batchFetchingGeneratorWrapper().
It should be a matter of :
fixing delay()
making appropriate returns to make the recursion work
ensuring that the function returns Promise.
Almost undoubtedly (syntactically) simpler with async/await but here it is with old-fashioned thens :
exports.batchFetchingGeneratorWrapper = function(generator, batchArray) {
let evalNextValue = generator.next();
let delay = (t) => {
return new Promise(resolve => {
setTimeout(resolve, t);
});
};
if (!evalNextValue.done) {
return exports.batchPromiseWrapper(evalNextValue.value).then(data => {
return delay(5000).then(() => {
return exports.batchFetchingGeneratorWrapper(generator, batchArray.concat(data || []));
});
});
} else {
console.log("yay done!", batchArray);
return Promise.resolve(batchArray); // <<< promise wrapped to ensure that batchFetchingGeneratorWrapper() returns Promise
}
};
And chain the batchFetchingGeneratorWrapper() call appropriately :
promiseDataWrapper
.then(data => gatherData.cleanUpVODData(data))
.then(data => {
function* batchFetching(batchArray) {
for (let i = 0; i < batchArray.length; i++) {
yield batchArray[i];
}
}
return gatherData.batchFetchingGeneratorWrapper(batchFetching(data), []).then(batchArrResult => {
console.log('batchArrResult: ', batchArrResult);
return batchArrResult;
});
}).catch(error => {
console.log(error);
});

How can I get rid of the "setInterval" in this code construct?

I need to wait for the necessary changes in the object to finish the function and return the result to the caller. But I could not think of anything better than using "setInterval". I think I'm doing something wrong.
async checkLockBox ({ state, dispatch, commit }, lockBox) {
if (lockBox.layers === 0) {
commit('lockBox', null);
return lockBox.result;
}
await commit('lockBox', lockBox);
return new Promise((resolve) => {
setInterval(async () => {
if (state.lockBox !== null) {
if (state.lockBox.layers === 0) {
await resolve(state.lockBox.result);
await commit('lockBox', null);
}
}
}, 100);
});
},

Categories