Integrating debounce to search input - javascript

I am trying to integrate debounce to a search input so i can search through fetched data (after getting the data ) with the full term, i have this debounce function in the App.js :
debounce = (callback, delay) => {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => callback(...args), delay);
}
}
debouncedTerm = this.debounce(text => console.log(text), 300);
I have also this method in the App.js
onSearchChanged = data => {
const searchBar = data.target.value.toLowerCase();
this.debouncedTerm(searchBar)
this.setState({
searchBar: searchBar,
}, () => {
let newData = {...this.state};
if( typeof this.props.source !== "undefined"){
newData.source = this.props.source
}
newData.params = {
searchBar : this.state.searchBar
}
Api.fetchQuestions(newData.params)
.catch( error => {
if (typeof error.message !== "undefined"){
newData.config.formMessage = {
message : error.message,
success : false,
}
newData.widgetStatus = false;
this.setState(newData)
}
return {data:{data:[]}}
})
.then( response => {
if(response.data.status === 'success'){
return response.data.data;
}
this.setState({
questions: [...response.data.questions.items],
loading: false
});
})
});
};
FYI : I pass the value of the input (searchBar) as a parameter in newData.params
'URL/questions?client_id='+params.client_id+'&term='+params.searchBar,
How can i integrate debouncedTerm in the method onSearchChanged
I have the search input in a child component
<InputSearch
type="search"
placeholder="Search"
onChange={props.searchCallback}
/>

this is a part of the code I wrote recently:
export function debounceFetch(fn, delay) {
let createdTimeout;
let controller;
function onCancel() {
controller?.abort();
createdTimeout?.cancel();
}
async function debounced(...args) {
onCancel();
controller = new AbortController();
createdTimeout = timeout(delay);
await createdTimeout.delay;
return fn(...args, controller.signal);
}
return [
debounced,
onCancel,
];
}
It cancels the fetch request too,
and this is the timeout part:
function timeout(ms) {
let timeoutRef;
let rejectRef;
const delay = new Promise((resolve, reject) => {
timeoutRef = setTimeout(() => {
resolve('timeout done');
}, ms);
rejectRef = () => {
reject(new Error('cancel timeout'));
};
});
return {
delay,
cancel() {
clearTimeout(timeoutRef);
rejectRef();
},
};
}

Related

How to get acces to the PromiseResult (react)

this is my code:
const sendBoardId = async boardId => {
let result;
try {
result = await axios.get(`${fetchConfig.prefix}/game/get_board_by_id`, {
params: {
boardId,
},
});
} catch (e) {
console.log(e);
}
console.log('board:', result.data);
if (result.data == null || result.data.length == 0 || result.data == undefined) {
const BoardData = [];
return BoardData;
}
return result.data;
};
const Board = sendBoardId(1);
console.log('aaa', Board);
export { Board };
In the "aaa" console log I keep getting promise, and only in the promise result I got what I needed,
I want to export the promise result and not all the promise it self.
How should I do it?
To use Promise
const sendBoardId = async (boardId) =>
new Promise(async (resolve, reject) => {
let result;
try {
result = await axios.get(`${fetchConfig.prefix}/game/get_board_by_id`, {
params: {
boardId,
},
});
} catch (e) {
console.log(e);
reject(e);
}
console.log("board:", result.data);
if (
result.data === null ||
result.data.length === 0 ||
result.data === undefined
) {
resolve([]);
}
resolve(result.data);
});
const Board = sendBoardId; // UseLess
console.log("aaa", Board);
export { Board }; // Better to direct export sendBoardId
And use:
import {Board} from "...........";
const xyz = async() =>{
const data = await Board(1);
}

Async module returning promise [object Promise]

I am trying to export the value with instrument variable. however data is returning as [object Promise] than object. How can I assign module variable with the final result rather than the promise object.
var instruments = {
data: async () => {
return new Promise((resolve, reject) => {
/// Respond after retrieving the data
resolve({result : "...." }
);
}
}
var symbols = async () => {
const res = await instruments.data();
return res;
}
module.exports.instrument = symbols().then((data) => {
console.log('data');
return data;
}).catch((e) => {
console.log('error');
return {}
});
It looks like you want a singleton cache. Here is a basic implementation
cache.js
let data = {}
module.exports = {
getData: () => {
return data
},
setData: newData => {
data = newData
return
},
}
No need for async here. I would separate this code with the code that retrieves data.
fetchData.js
const cache = require('./cache')
const fetchData = () => {} // fetch data code here
fetchData().then(data => {
cache.setData(data)
})
try this
var instruments = {
data: () => {
return new Promise((resolve, reject) => {
/// Respond after retrieving the data
resolve({result : "...." });
}
}
var symbols = async () => {
const res = await instruments.data();
return res;
}
module.exports.instrument = symbols;
then import instrument method to call and then call
const instrument = require("./filepath");
instrument().then((data) => {
console.log('data');
}).catch((e) => {
console.log(e);
});
If your async function instruments.data() called, it'll await return Promise.
just append await at return for your expected result.
var instruments = {
data: async () => {
return await new Promise((resolve, reject) => {
// Respond after retrieving the data
resolve({result : "...." });
}
}
or remove async. it's same as above.
var instruments = {
data: () => {
return new Promise((resolve, reject) => {
// Respond after retrieving the data
resolve({result : "...." });
}
}

React setTimeout and clearTimeout

Recently I am creating a website using React and I found out that I kind of use a lot of 'setTimeOut()' and I know that from React documentation sometimes you need to clean up some things when component unmount(To be honest, I am not fully understand about this clean up thing), apparently recently I saw a posts saying that 'setTimeOut()' need to be clean up too but how do I clean up functions that I call in 'useEffect()' which I am using 'setTimeOut()' inside the function?
Here are my codes:
useEffect(() => {
createContent();
handleMobileContainerView();
});
const createContent = () => {
if (contentCompShowStatus) {
for (let key in btnStatus) {
if (btnStatus.hasOwnProperty(key)) {
if (btnStatus[key] === true) {
if (key === 'aboutBtn') {
delayContent('about-contents');
} else if (key === 'skillsBtn') {
delayContent('skills-contents');
} else if (key === 'projectsBtn') {
delayContent('projects-contents');
}
}
}
}
}
};
const delayContent = (content) => {
if (firstTime) {
setTimeout(() => {
setCurrentContent(content);
setFirstTime(false);
}, 200);
} else if (!firstTime) {
setTimeout(() => {
setCurrentContent(content);
}, 450);
}
};
As you can see above codes, 'createContent()' is in 'useEffect()' and is calling a function name 'delayContent()' which is using 'setTimeout()'.
Do I need to do clean up with this kind of case?
How do I do clean up with this kind of case? (function inside of function which is using 'setTimeOut()' and is called in 'useEffect()')
You can return timerId while creating timeOut. And on unmount u can clean using return function of useEffect.
Unmount:
useEffect(() => {
const timerId = createContent();
handleMobileContainerView();
return () => {
clearTimeout(timerId);
};
}, []);
Return TimerId:
const delayContent = (content) => {
let timerId;
if (firstTime) {
timerId = setTimeout(() => {
setCurrentContent(content);
setFirstTime(false);
}, 200);
} else if (!firstTime) {
timerId = setTimeout(() => {
setCurrentContent(content);
}, 450);
}
return timerId;
};
// All code:
function A() {
useEffect(() => {
const timerId = createContent();
handleMobileContainerView();
return () => {
clearTimeout(timerId);
};
}, []);
const createContent = () => {
if (contentCompShowStatus) {
for (let key in btnStatus) {
if (btnStatus.hasOwnProperty(key)) {
if (btnStatus[key] === true) {
if (key === "aboutBtn") {
return delayContent("about-contents");
} else if (key === "skillsBtn") {
return delayContent("skills-contents");
} else if (key === "projectsBtn") {
return delayContent("projects-contents");
}
}
}
}
}
};
const delayContent = (content) => {
let timerId;
if (firstTime) {
timerId = setTimeout(() => {
setCurrentContent(content);
setFirstTime(false);
}, 200);
} else if (!firstTime) {
timerId = setTimeout(() => {
setCurrentContent(content);
}, 450);
}
return timerId;
};
}
You can use useEffect to return a function which should do the job of cleaning up of the setTimouts and setIntervals. For eg,
useEffect(() => {
const timer = setTimeout(someFunc, 100);
return () => clearTimeout(timer);
});
To cleanup setTimouts, use clearTimeout and clearInterval for setInterval. Documentation
As far as your code is concerned,
useEffect(() => {
const timers = createContent();
handleMobileContainerView();
return () => timers.forEach(timer => window.clearTimeout(timer));
});
const createContent = () => {
let timers = [];
if (contentCompShowStatus) {
for (let key in btnStatus) {
if (btnStatus.hasOwnProperty(key)) {
if (btnStatus[key] === true) {
if (key === 'aboutBtn') {
timers.push(delayContent('about-contents'));
} else if (key === 'skillsBtn') {
timers.push(delayContent('skills-contents'));
} else if (key === 'projectsBtn') {
timers.push(delayContent('projects-contents'));
}
}
}
}
}
return timers;
};
const delayContent = (content) => {
let timer;
if (firstTime) {
timer = setTimeout(() => {
setCurrentContent(content);
setFirstTime(false);
}, 200);
} else if (!firstTime) {
timer = setTimeout(() => {
setCurrentContent(content);
}, 450);
}
return timer;
};

mergePromise(...).then is not a function

When I run the code, I get the error
mergePromise(...).then is not a function.
I want to know why I got this error.
const timeout = ms => new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, ms);
});
const ajax1 = () => timeout(2000).then(() => {
console.log('1');
return 1;
});
const ajax2 = () => timeout(1000).then(() => {
console.log('2');
return 2;
});
const ajax3 = () => timeout(2000).then(() => {
console.log('3');
return 3;
});
const mergePromise = ajaxArray => {
const data=[];
ajaxArray[0]().then(i=>data.push(i));
timeout(1005).then(() => {
ajaxArray[1]().then(i=>data.push(i));
});
timeout(10).then(() => {
ajaxArray[2]().then(i=>data.push(i));
});
return data;
};
I guess maybe the timeout function has some mistake. What am I doing wrong?
Maybe you can try return Promise.resolve(data) instead, it would return a promise, which is what you need.

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);
});

Categories