How to reduce repeated strapi api calls - javascript

I have the following code
const getData = async (): Promise<void> => {
const { page, pageSize } = pageOption
try {
setShowContentLoader(true)
const { data: isActiveData } = await axiosStrapi.get('/changelog-sellers?isActive=true&_sort=id:DESC')
const { data: pageOptionRows } = await axiosStrapi.get(`/changelog-sellers?_start=${(page - 1) * pageSize}&_limit=${pageSize}&_sort=id:DESC`)
const { data: rows } = await axiosStrapi.get(`/changelog-sellers?type=${type}&_start=${(page - 1) * pageSize}&_limit=${pageSize}&_sort=id:DESC`)
const { data: oldRows } = await axiosStrapi.get('/changelog-sellers?_start=0&_limit=10&_sort=id:DESC')
setFeaturedPosts(isActiveData.slice(0, 3))
setOldChangelogSellers(oldRows)
if (type === 'all') {
const { data: count } = await axiosStrapi.get('/changelog-sellers/count')
setTotal(count)
setChangelogSellers(pageOptionRows)
} else {
const { data: tabTitleCount } = await axiosStrapi.get(`/changelog-sellers/count?type=${type}`)
setTotal(tabTitleCount)
setChangelogSellers(rows)
}
} catch (error) {
console.log('error', error)
} finally {
setShowContentLoader(false)
}
}
I am repeatedly calling /changelog-sellers to get different kinds of data. Is there a way to simplify my code so that I only call /changelog-sellers once? Or is it impossible because I need to pass different parameters to each of the different api call even though they are all sourced from /changelog-sellers?

Related

Redshift SELECT query returns error ActiveStatementsExceededException: Active statements exceeded the allowed quota

I need to query some data from Redshift in my aws lambda code and I do it several times with different parameters, pretty soon I get the error:
ActiveStatementsExceededException: Active statements exceeded the allowed quota (200).
How can I send thousands of queries to Redshift without hitting a limit?
Here is my JS code:
...
let results = await redshiftQuery(connectionInfo, "SELECT * from db.games where game_id=:game_id", {game_id: 12345})
...
async function redshiftQuery(conInfo, query, params = {}) {
let rsParams = []
for(let key in params) {
rsParams.push( { name: key, value: params[key].toString() })
}
const executeStatementInput = {
ClusterIdentifier: conInfo.clusterId,
Database: conInfo.database,
SecretArn: conInfo.secret,
WithEvent: false,
Sql: query
}
if(rsParams.length) {
executeStatementInput.Parameters = rsParams
}
let results = []
try {
let exResponse = await redshiftDataApiClient.executeStatement(executeStatementInput).promise()
if(!exResponse.Id) return results
let describeStatementInfo = null
while(true) {
let { Status: queryStatus, ...rest } = await redshiftDataApiClient.describeStatement({ Id: exResponse.Id }).promise()
describeStatementInfo = rest
if(["FAILED", "FINISHED"].includes(queryStatus)) {
break
}
await sleepMillis(200)
}
if (describeStatementInfo && describeStatementInfo.HasResultSet) {
let result = await redshiftDataApiClient.getStatementResult({ Id: exResponse.Id }).promise()
convertResult(result, results)
while(result.NextToken) {
result = await redshiftDataApiClient.getStatementResult({ Id: exResponse.Id, NextToken: result.NextToken }).promise()
convertResult(result, results)
}
}
} catch (e) {
console.error("Redshift Error", e)
}
return results
}

How do you pass variables to other JS modules with Fetch API?

A JavaScript app uses Web Audio API to create sounds from JSON data. I am fetching weather data, going through the JSON data and setting their properties to variables then using those variables to manipulate my application and create sounds. Each function in it's own JavaScript module script file. The main.js not shown here is the entry point to app.
A sample JSON that will get replaced with real weather data.
dummy-data.json
{
"weather": {
"temp": 4,
"rain": 1,
"wind": 1.2
}
}
The fetch API logic.
fetchWeather.js
import { manageData} from './manageScript.js';
const DUMMY = '../dummy-data.json';
const fetchWeather = () => {
fetch(DUMMY)
.then((res) => {
return res.json();
})
.then((data) => {
manageData(data); // attaches JSON weather properties to variables
})
.catch((error) => {
console.log(error);
});
};
export { fetchWeather };
Attaches the JSON data to variables.
manageScript.js
function manageData(data) {
let rain = data.weather.rain;
//let wind = data.weather.wind;
let rainProbability;
if (rain == 1) {
rainProbability = 1;
}
else {
rainProbability = 0;
}
return rainProbability; // not sure how to return the data....?
};
export { manageData };
I want the variables from manageData function above to work here
makeSynth.js
import { manageData } from './manageScript.js';
const createSynth = () => {
//Web Audio API stuff goes here to create sounds from the variables.
//How do I get the variables to work here. Code below does not work!
let soundOfRain = manageData().rainProbability;
console.log(soundOfRain);
};
You can achieve this by refactoring your promises into a async/await pattern then returning the result (a different method of dealing with promises). Also - your createSynth function should be calling fetchWeather, not manageScript
dummy-data.json
{
"weather": {
"temp": 4,
"rain": 1,
"wind": 1.2
}
}
manageScript.js
function manageData(data) {
let rain = data.weather.rain;
//let wind = data.weather.wind;
let rainProbability;
if (rain == 1) {
rainProbability = 1;
} else {
rainProbability = 0;
}
return rainProbability;
}
export { manageData };
fetchWeather.js
import { manageData } from "./manageScript.js";
const DUMMY = "../dummy-data.json";
// Use async/await to be able to return a variable out from the promise
const fetchWeather = async () => {
const raw = await fetch(DUMMY);
const json_data = await raw.json();
const rain = manageData(json_data);
// Now you should be able to return the variable back out of the function
return rain;
};
export { fetchWeather };
makeSynth.js
import { fetchWeather } from "./fetchWeather.js";
const createSynth = async () => {
//Web Audio API stuff goes here to create sounds from the variables.
//Need to call fetchWeather (which in turn will call manageData)
let soundOfRain = await fetchWeather();
console.log(soundOfRain);
};
createSynth();
// dummy-data.json
{
"weather": {
"temp": 4,
"rain": 1,
"wind": 1.2
}
}
// fetchWeather.js
import { getRainProbability } from './get-rain-probability.js'
import { createSynth } from './create-synth.js'
const DUMMY = '../dummy-data.json'
const fetchWeather = () => {
return fetch(DUMMY)
.then((res) => res.json())
.then((data) => {
createSynth({ rainProbability: getRainProbability(data) })
})
.catch((error) => {
console.log(error)
});
};
export { fetchWeather }
// get-rain-probability.js
function getRainProbability(data) {
let rain = data.weather.rain
let rainProbability;
if (rain == 1) {
rainProbability = 1;
}
else {
rainProbability = 0;
}
return rainProbability; // not sure how to return the data....?
};
// create-synth.js
const createSynth = ({ rainProbability }) => {
const soundOfRain = //WebAPI stuff for audio using `rainProbability`
console.log(soundOfRain);
};
export { createSynth }
You can add data as a property of manageData that would return this, and access it with manageData().data; :
fetchWeather.js
const fetchWeather = () => {
fetch(DUMMY)
.then(res => {
return res.json();
})
.then(data => {
manageData.data = data; // attaches JSON weather properties to variables
})
.catch(error => {
console.log(error);
});
};
manageScript.js
function manageData() {
// ...
return this;
}
makeSynth.js
let soundOfRain = manageData().data.rainProbability;

How to use dialogs with dispatch service?

I cannot use beginDialog with the LUIS dispatch. I want to use processHomeAutomation function to begin a new dialog but it gives me an error.
[onTurnError]: Error: DialogContext.beginDialog(): A dialog with an id
of 'TOP_LEVEL_DIALOG' wasn't found.
I imported TOP_LEVEL_DIALOG but still does not work. It only works with MainDialog which is the name of the current class.
const { ConfirmPrompt, DialogSet, DialogTurnStatus, OAuthPrompt, WaterfallDialog } = require('botbuilder-dialogs');
const { LogoutDialog } = require('./logoutDialog');
const { TopLevelDialog, TOP_LEVEL_DIALOG } = require('./topLevelDialog');
const { LuisRecognizer, QnAMaker } = require('botbuilder-ai');
const CONFIRM_PROMPT = 'ConfirmPrompt';
const MAIN_DIALOG = 'MainDialog';
const MAIN_WATERFALL_DIALOG = 'MainWaterfallDialog';
const OAUTH_PROMPT = 'OAuthPrompt';
let loggedIn = true;
class MainDialog extends LogoutDialog {
constructor() {
super(MAIN_DIALOG, process.env.connectionName);
this.addDialog(new TopLevelDialog());
this.addDialog(new OAuthPrompt(OAUTH_PROMPT, {
connectionName: process.env.connectionName,
text: 'Please Sign In',
title: 'Sign In',
timeout: 300000
}));
this.addDialog(new ConfirmPrompt(CONFIRM_PROMPT));
this.addDialog(new WaterfallDialog(MAIN_WATERFALL_DIALOG, [
this.promptStep.bind(this),
this.loginStep.bind(this),
this.displayTokenPhase1.bind(this),
this.displayTokenPhase2.bind(this)
]));
}
/**
* The run method handles the incoming activity (in the form of a DialogContext) and passes it through the dialog system.
* If no dialog is active, it will start the default dialog.
* #param {*} dialogContext
*/
async run(context, accessor) {
console.log(this.id)
if (loggedIn) {
const dialogSet = new DialogSet(accessor);
dialogSet.add(this);
const dialogContext = await dialogSet.createContext(context);
const results = await dialogContext.continueDialog();
const dispatchRecognizer = new LuisRecognizer({
applicationId: process.env.LuisAppId,
endpointKey: process.env.LuisAPIKey,
endpoint: `https://${process.env.LuisAPIHostName}.api.cognitive.microsoft.com`
}, {
includeAllIntents: true,
includeInstanceData: true
}, true);
const qnaMaker = new QnAMaker({
knowledgeBaseId: process.env.QnAKnowledgebaseId,
endpointKey: process.env.QnAAuthKey,
host: process.env.QnAEndpointHostName
});
this.dispatchRecognizer = dispatchRecognizer;
this.qnaMaker = qnaMaker;
const recognizerResult = await dispatchRecognizer.recognize(context);
// Top intent tell us which cognitive service to use.
const intent = LuisRecognizer.topIntent(recognizerResult);
// Next, we call the dispatcher with the top intent.
await this.dispatchToTopIntentAsync(context, intent, recognizerResult, dialogContext, results, dialogSet);
} else {
const dialogSet = new DialogSet(accessor);
dialogSet.add(this);
const dialogContext = await dialogSet.createContext(context);
const results = await dialogContext.continueDialog();
if (results.status === DialogTurnStatus.empty) {
console.log(this.id)
await dialogContext.beginDialog(this.id);
}
}
}
async promptStep(stepContext) {
return await stepContext.beginDialog(OAUTH_PROMPT);
}
async loginStep(stepContext) {
// Get the token from the previous step. Note that we could also have gotten the
// token directly from the prompt itself. There is an example of this in the next method.
const tokenResponse = stepContext.result;
if (tokenResponse) {
loggedIn = true;
await stepContext.context.sendActivity('You are now logged in.');
return await stepContext.prompt(CONFIRM_PROMPT, 'Would you like to view your token?');
}
await stepContext.context.sendActivity('Login was not successful please try again.');
return await stepContext.endDialog();
}
async displayTokenPhase1(stepContext) {
await stepContext.context.sendActivity('Thank you.');
const result = stepContext.result;
if (result) {
return await stepContext.beginDialog(OAUTH_PROMPT);
}
return await stepContext.endDialog();
}
async displayTokenPhase2(stepContext) {
const tokenResponse = stepContext.result;
if (tokenResponse) {
await stepContext.context.sendActivity(`Here is your token ${tokenResponse.token}`);
}
return await stepContext.endDialog();
}
/// QNA STUFF STATS HERE
async dispatchToTopIntentAsync(context, intent, recognizerResult, dialogContext, results) {
switch (intent) {
case 'automation':
await this.processHomeAutomation(context, recognizerResult.luisResult, dialogContext, results);
break;
case 'qna':
await this.processSampleQnA(context);
break;
default:
this.logger.log(`Dispatch unrecognized intent: ${intent}.`);
await context.sendActivity(`Dispatch unrecognized intent: ${intent}.`);
break;
}
}
async processHomeAutomation(context, luisResult, dialogContext, results, dialogSet) {
return await dialogContext.beginDialog(TOP_LEVEL_DIALOG);
}
async processSampleQnA(context) {
this.logger.log('processSampleQnA');
const results = await this.qnaMaker.getAnswers(context);
if (results.length > 0) {
await context.sendActivity(`${results[0].answer}`);
} else {
await context.sendActivity('Sorry, could not find an answer in the Q and A system.');
}
}
}
module.exports.MainDialog = MainDialog;

Handling multiple ajax requests, only do the last request

I'm doing a project that fetch different types of data from SWAPI API (people, planets, etc.) using react but I have an issue with multiple Ajax request.
The problem is when I quickly request from 2 different URL for example, 'species' and 'people', and my last request is 'species' but the load time of 'people' is longer, I will get 'people' instead.
What I want is to get the data of the last clicked request, if that make sense.
How do I achieve that? All the solution I found from Google is using jQuery.
Here's a slice of my code in src/app.js (root element) :
constructor(){
super();
this.state = {
searchfield: '',
data: [],
active: 'people'
}
}
componentDidMount() {
this.getData();
}
componentDidUpdate(prevProps, prevState) {
if(this.state.active !== prevState.active) {
this.getData();
}
}
getData = async function() {
console.log(this.state.active);
this.setState({ data: [] });
let resp = await fetch(`https://swapi.co/api/${this.state.active}/`);
let data = await resp.json();
let results = data.results;
if(data.next !== null) {
do {
let nextResp = await fetch(data.next);
data = await nextResp.json();
let nextResults = data.results
results.push(nextResults);
results = results.reduce(function (a, b) { return a.concat(b) }, []);
} while (data.next);
}
this.setState({ data: results});
}
categoryChange = (e) => {
this.setState({ active: e.target.getAttribute('data-category') });
}
render() {
return (
<Header searchChange={this.searchChange} categoryChange={this.categoryChange}/>
);
}
I made a gif of the problem here.
Sorry for the bad formatting, I'm writing this on my phone.
You have to store your requests somewhere and to abandon old ones by making only one request active. Something like:
getData = async function() {
console.log(this.state.active);
this.setState({ data: [] });
// my code starts here
if (this.controller) { controller.abort() }
this.controller = new AbortController();
var signal = controller.signal;
let resp = await fetch(`https://swapi.co/api/${this.state.active}/`, { signal });
let data = await resp.json();
let results = data.results;
if(data.next !== null) {
do {
let nextResp = await fetch(data.next);
data = await nextResp.json();
let nextResults = data.results
results.push(nextResults);
results = results.reduce(function (a, b) { return a.concat(b) }, []);
} while (data.next);
}
this.setState({ data: results});
}

async await inside function not working properly?

I have this function, that i need to define an async function inside it:
_refetchConnection = (page) => { // query for cursor page
const refetchVariables = async (fragmentVariables) => {
let pageCursor;
if(page !== 1) {
const getAfterCursorQueryText = `
query($count: Int!, $cursor:String) {# filename+Query
viewer {
publicTodos (first: $count, after: $cursor) {
edges {
cursor
node {
id
}
}
pageInfo { # for pagination
hasPreviousPage
startCursor
hasNextPage
endCursor
}
}
}
}`;
let cursor = fragmentVariables.cursor;
let count = 5;
const getAfterCursorQuery = { text: getAfterCursorQueryText };
const result = await this.props.relay.environment._network.fetch(getAfterCursorQuery, {cursor, count});
pageCursor = result.data.viewer.publicTodos.pageInfo.endCursor;
} else if (page === 1) {
pageCursor = null;
}
return {
cursor: pageCursor,
count:5
}
}
this.props.relay.refetch(refetchVariables, null);
};
but there's no returned value on refetchVariables, it only had when I do not use async but i need to perform await for this code, and I need access on fragmentVariables:
const result = await this.props.relay.environment._network.fetch(getAfterCursorQuery, {cursor, count});
maybe making refetchVariables not an async works? but I have no idea how to code it. help? btw this is the value returned on async refetchVariables:
ƒ refetchVariables(_x2) {
return _ref3.apply(this, arguments);
}

Categories

Resources