feat: request cancel implementation in electron

This commit is contained in:
Anoop M D 2022-10-16 03:06:46 +05:30
parent 118658822d
commit d8cdd2ad8b
5 changed files with 89 additions and 40 deletions

View File

@ -18,9 +18,8 @@ import {
} from 'utils/collections'; } from 'utils/collections';
import { collectionSchema, itemSchema } from '@usebruno/schema'; import { collectionSchema, itemSchema } from '@usebruno/schema';
import { waitForNextTick } from 'utils/common'; import { waitForNextTick } from 'utils/common';
import cancelTokens, { saveCancelToken, deleteCancelToken } from 'utils/network/cancelTokens';
import { getCollectionsFromIdb, saveCollectionToIdb, deleteCollectionInIdb } from 'utils/idb'; import { getCollectionsFromIdb, saveCollectionToIdb, deleteCollectionInIdb } from 'utils/idb';
import { sendNetworkRequest } from 'utils/network'; import { sendNetworkRequest, cancelNetworkRequest } from 'utils/network';
import { import {
loadCollections, loadCollections,
@ -208,17 +207,15 @@ export const saveRequest = (itemUid, collectionUid) => (dispatch, getState) => {
}; };
export const sendRequest = (item, collectionUid) => (dispatch) => { export const sendRequest = (item, collectionUid) => (dispatch) => {
const axiosRequest = axios.CancelToken.source();
const cancelTokenUid = uuid(); const cancelTokenUid = uuid();
saveCancelToken(cancelTokenUid, axiosRequest);
dispatch(requestSent({ dispatch(requestSent({
itemUid: item.uid, itemUid: item.uid,
collectionUid: collectionUid, collectionUid: collectionUid,
cancelTokenUid: cancelTokenUid cancelTokenUid: cancelTokenUid
})); }));
sendNetworkRequest(item, {cancelToken: axiosRequest.token}) sendNetworkRequest(item, {cancelTokenUid: cancelTokenUid})
.then((response) => { .then((response) => {
if(response && response.status !== -1) { if(response && response.status !== -1) {
return dispatch(responseReceived({ return dispatch(responseReceived({
@ -228,18 +225,18 @@ export const sendRequest = (item, collectionUid) => (dispatch) => {
})); }));
} }
}) })
.then(() => deleteCancelToken(cancelTokenUid))
.catch((err) => console.log(err)); .catch((err) => console.log(err));
}; };
export const cancelRequest = (cancelTokenUid, item, collection) => (dispatch) => { export const cancelRequest = (cancelTokenUid, item, collection) => (dispatch) => {
if(cancelTokenUid && cancelTokens[cancelTokenUid]) { cancelNetworkRequest(cancelTokenUid)
cancelTokens[cancelTokenUid].cancel(); .then(() => {
dispatch(requestCancelled({ dispatch(requestCancelled({
itemUid: item.uid, itemUid: item.uid,
collectionUid: collection.uid collectionUid: collection.uid
})) }))
} })
.catch((err) => console.log(err));
}; };
export const newFolder = (folderName, collectionUid, itemUid) => (dispatch, getState) => { export const newFolder = (folderName, collectionUid, itemUid) => (dispatch, getState) => {

View File

@ -1,22 +1,20 @@
const axios = require('axios'); const axios = require('axios');
const FormData = require('form-data'); import { saveCancelToken, deleteCancelToken } from 'utils/network/cancelTokens';
const { forOwn, extend } = require('lodash');
export const sendHttpRequestInBrowser = async (request) => { export const sendHttpRequestInBrowser = async (request, options) => {
try { try {
// make axios work in node using form data if(options && options.cancelTokenUid) {
// reference: https://github.com/axios/axios/issues/1006#issuecomment-320165427 const cancelToken = axios.CancelToken.source();
if(request.headers && request.headers['content-type'] === 'multipart/form-data') { request.cancelToken = cancelToken.token;
const form = new FormData(); saveCancelToken(options.cancelTokenUid, cancelToken);
forOwn(request.data, (value, key) => {
form.append(key, value);
});
extend(request.headers, form.getHeaders());
request.data = form;
} }
const result = await axios(request); const result = await axios(request);
if(options && options.cancelTokenUid) {
deleteCancelToken(options.cancelTokenUid);
}
return { return {
status: result.status, status: result.status,
headers: result.headers, headers: result.headers,

View File

@ -3,8 +3,10 @@ import filter from 'lodash/filter';
import qs from 'qs'; import qs from 'qs';
import { rawRequest, gql } from 'graphql'; import { rawRequest, gql } from 'graphql';
import { sendHttpRequestInBrowser } from './browser'; import { sendHttpRequestInBrowser } from './browser';
import { isElectron } from 'utils/common/platform';
import cancelTokens, { deleteCancelToken } from 'utils/network/cancelTokens';
const sendNetworkRequest = async (item, options) => { export const sendNetworkRequest = async (item, options) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if(item.type === 'http-request') { if(item.type === 'http-request') {
const timeStart = Date.now(); const timeStart = Date.now();
@ -42,10 +44,6 @@ const sendHttpRequest = async (request, options) => {
headers: headers headers: headers
}; };
if(options && options.cancelToken) {
axiosRequest.cancelToken = options.cancelToken;
}
if(request.body.mode === 'json') { if(request.body.mode === 'json') {
axiosRequest.headers['content-type'] = 'application/json'; axiosRequest.headers['content-type'] = 'application/json';
try { try {
@ -84,15 +82,16 @@ const sendHttpRequest = async (request, options) => {
console.log('>>> Sending Request'); console.log('>>> Sending Request');
console.log(axiosRequest); console.log(axiosRequest);
// Todo: Choose based on platform (web/desktop) if(isElectron()) {
sendHttpRequestInBrowser(axiosRequest) ipcRenderer
.invoke('send-http-request', axiosRequest, options)
.then(resolve) .then(resolve)
.catch(reject); .catch(reject);
} else {
// ipcRenderer sendHttpRequestInBrowser(axiosRequest, options)
// .invoke('send-http', axiosRequest) .then(resolve)
// .then(resolve) .catch(reject);
// .catch(reject); }
}); });
}; };
@ -109,6 +108,23 @@ const sendGraphqlRequest = async (request,) => {
} }
}; };
export { export const cancelNetworkRequest = async (cancelTokenUid) => {
sendNetworkRequest if(isElectron()) {
return new Promise((resolve, reject) => {
ipcRenderer
.invoke('cancel-http-request', cancelTokenUid)
.then(resolve)
.catch(reject);
});
}
return new Promise((resolve, reject) => {
if(cancelTokenUid && cancelTokens[cancelTokenUid]) {
cancelTokens[cancelTokenUid].cancel();
deleteCancelToken(cancelTokenUid);
resolve();
} else {
reject(new Error("cancel token not found"));
}
});
}; };

View File

@ -2,10 +2,11 @@ const axios = require('axios');
const FormData = require('form-data'); const FormData = require('form-data');
const { ipcMain } = require('electron'); const { ipcMain } = require('electron');
const { forOwn, extend } = require('lodash'); const { forOwn, extend } = require('lodash');
const { cancelTokens, saveCancelToken, deleteCancelToken } = require('../utils/cancel-token');
const registerNetworkIpc = () => { const registerNetworkIpc = () => {
// handler for sending http request // handler for sending http request
ipcMain.handle('send-http-request', async (event, request) => { ipcMain.handle('send-http-request', async (event, request, options) => {
try { try {
// make axios work in node using form data // make axios work in node using form data
// reference: https://github.com/axios/axios/issues/1006#issuecomment-320165427 // reference: https://github.com/axios/axios/issues/1006#issuecomment-320165427
@ -18,8 +19,18 @@ const registerNetworkIpc = () => {
request.data = form; request.data = form;
} }
if(options && options.cancelTokenUid) {
const cancelToken = axios.CancelToken.source();
request.cancelToken = cancelToken.token;
saveCancelToken(options.cancelTokenUid, cancelToken);
}
const result = await axios(request); const result = await axios(request);
if(options && options.cancelTokenUid) {
deleteCancelToken(options.cancelTokenUid);
}
return { return {
status: result.status, status: result.status,
headers: result.headers, headers: result.headers,
@ -41,6 +52,18 @@ const registerNetworkIpc = () => {
}; };
} }
}); });
ipcMain.handle('cancel-http-request', async (event, cancelTokenUid) => {
return new Promise((resolve, reject) => {
if(cancelTokenUid && cancelTokens[cancelTokenUid]) {
cancelTokens[cancelTokenUid].cancel();
deleteCancelToken(cancelTokenUid);
resolve();
} else {
reject(new Error("cancel token not found"));
}
});
});
}; };
module.exports = registerNetworkIpc; module.exports = registerNetworkIpc;

View File

@ -0,0 +1,15 @@
const cancelTokens = {};
const saveCancelToken = (uid, axiosRequest) => {
cancelTokens[uid] = axiosRequest;
}
const deleteCancelToken = (uid) => {
delete cancelTokens[uid];
}
module.exports = {
cancelTokens,
saveCancelToken,
deleteCancelToken
};