Socket
Book a DemoInstallSign in
Socket

debounce-search-abstraction

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

debounce-search-abstraction - npm Package Compare versions

Comparing version

to
3.1.0

50

dist/debounce-search-abstraction.es.js

@@ -13,25 +13,37 @@ var __defProp = Object.defineProperty;

__publicField(this, "debouncedQueryProcessor");
this.debouncedQueryProcessor = debounce((seq, query) => {
if (seq === this.seq) {
if (!query && typeof options.emptyQueryResult === "function") {
options.resultsProcessor(options.emptyQueryResult());
} else {
options.resultsProvider({
query,
setResults: (result) => {
if (seq === this.seq) {
options.resultsProcessor(result);
}
}
});
this.options = options;
this.debouncedQueryProcessor = debounce(
(seq, query) => {
if (seq === this.seq) {
this.lastQuery = query;
if (!query) {
this.options.resultsProcessor(
this.options.emptyQueryResult(),
query
);
} else {
this.options.resultsProvider({
query,
setResults: (result) => {
if (seq === this.seq) {
this.options.resultsProcessor(
result,
query
);
}
},
isQueryStillActual: () => seq === this.seq
});
}
}
}
}, options.debounceMs || 300);
},
this.options.debounceMs || 300
);
}
search(query, forceIfSame = false) {
if (query !== this.lastQuery || forceIfSame) {
this.lastQuery = query;
const queryProcessed = this.options.trimQuery ? query.trim() : query;
if (queryProcessed !== this.lastQuery || forceIfSame) {
this.seq += 1;
this.debouncedQueryProcessor(this.seq, query);
if (!query) {
this.debouncedQueryProcessor(this.seq, queryProcessed);
if (!queryProcessed) {
this.debouncedQueryProcessor.flush();

@@ -38,0 +50,0 @@ }

@@ -1,1 +0,1 @@

(function(e,s){typeof exports=="object"&&typeof module!="undefined"?s(exports,require("lodash")):typeof define=="function"&&define.amd?define(["exports","lodash"],s):(e=typeof globalThis!="undefined"?globalThis:e||self,s(e.DebounceSearch={},e._))})(this,function(e,s){"use strict";var f=Object.defineProperty;var h=(e,s,r)=>s in e?f(e,s,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[s]=r;var o=(e,s,r)=>(h(e,typeof s!="symbol"?s+"":s,r),r);class r{constructor(u){o(this,"seq",0);o(this,"lastQuery","");o(this,"debouncedQueryProcessor");this.debouncedQueryProcessor=s.debounce((t,i)=>{t===this.seq&&(!i&&typeof u.emptyQueryResult=="function"?u.resultsProcessor(u.emptyQueryResult()):u.resultsProvider({query:i,setResults:d=>{t===this.seq&&u.resultsProcessor(d)}}))},u.debounceMs||300)}search(u,t=!1){(u!==this.lastQuery||t)&&(this.lastQuery=u,this.seq+=1,this.debouncedQueryProcessor(this.seq,u),u||this.debouncedQueryProcessor.flush())}}function n(c){return new r(c)}e.DebounceSearch=r,e.makeDebounceSearch=n,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
(function(e,s){typeof exports=="object"&&typeof module!="undefined"?s(exports,require("lodash")):typeof define=="function"&&define.amd?define(["exports","lodash"],s):(e=typeof globalThis!="undefined"?globalThis:e||self,s(e.DebounceSearch={},e._))})(this,function(e,s){"use strict";var d=Object.defineProperty;var l=(e,s,o)=>s in e?d(e,s,{enumerable:!0,configurable:!0,writable:!0,value:o}):e[s]=o;var u=(e,s,o)=>(l(e,typeof s!="symbol"?s+"":s,o),o);class o{constructor(r){u(this,"seq",0);u(this,"lastQuery","");u(this,"debouncedQueryProcessor");this.options=r,this.debouncedQueryProcessor=s.debounce((i,t)=>{i===this.seq&&(this.lastQuery=t,t?this.options.resultsProvider({query:t,setResults:h=>{i===this.seq&&this.options.resultsProcessor(h,t)},isQueryStillActual:()=>i===this.seq}):this.options.resultsProcessor(this.options.emptyQueryResult(),t))},this.options.debounceMs||300)}search(r,i=!1){const t=this.options.trimQuery?r.trim():r;(t!==this.lastQuery||i)&&(this.seq+=1,this.debouncedQueryProcessor(this.seq,t),t||this.debouncedQueryProcessor.flush())}}function c(n){return new o(n)}e.DebounceSearch=o,e.makeDebounceSearch=c,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});

@@ -1,7 +0,9 @@

export declare type SearchResultsProcessor<R> = (result: R) => void;
export declare type SearchResultsProvider<R> = (options: {
export type SearchResultsProcessor<R> = (result: R, query: string) => void;
export type SetResultsCallback<R> = (result: R) => void;
export type SearchResultsProvider<R> = (options: {
query: string;
setResults: SearchResultsProcessor<R>;
setResults: SetResultsCallback<R>;
isQueryStillActual: () => boolean;
}) => void;
export declare type DebounceSearchOptions<R> = {
export type DebounceSearchOptions<R> = {
debounceMs: number;

@@ -11,2 +13,3 @@ resultsProvider: SearchResultsProvider<R>;

emptyQueryResult: () => R;
trimQuery?: boolean;
};

@@ -18,2 +21,3 @@ export interface IDebounceSearch {

export declare class DebounceSearch<R> implements IDebounceSearch {
private options;
private seq;

@@ -20,0 +24,0 @@ private lastQuery;

{
"name": "debounce-search-abstraction",
"version": "3.0.2",
"version": "3.1.0",
"description": "A tool to easily make the search debounce properly",

@@ -20,7 +20,7 @@ "keywords": [

"scripts": {
"dev": "vite",
"dev": "vite --config vite.demo.config.js",
"build": "tsc && vite build",
"preview": "vite preview",
"test": "jest",
"lint": "eslint --fix ."
"lint": "eslint *.js lib/*",
"lint:fix": "eslint --fix *.js lib/*"
},

@@ -46,23 +46,24 @@ "files": [

"peerDependencies": {
"lodash": "^4.17.21"
"lodash": "^4"
},
"dependencies": {
"lodash": "^4.17.21"
"lodash": "^4"
},
"devDependencies": {
"@types/jest": "^27.5.1",
"@types/lodash": "^4.14.182",
"@typescript-eslint/eslint-plugin": "^5.26.0",
"@typescript-eslint/parser": "^5.26.0",
"eslint": "^8.16.0",
"@types/jest": "^29.5.3",
"@types/lodash": "^4",
"@typescript-eslint/eslint-plugin": "^5.32.0",
"@typescript-eslint/parser": "^5.32.0",
"eslint": "^8.21.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-editorconfig": "^3.2.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^28.1.0",
"prettier": "^2.6.2",
"ts-jest": "^28.0.3",
"typescript": "^4.7.2",
"vite": "^2.9.9",
"vite-plugin-dts": "^1.2.0"
"eslint-plugin-prettier": "^4.2.1",
"jest": "^28.1.3",
"prettier": "^2.7.1",
"ts-jest": "^28.0.7",
"typescript": "^4.7.4",
"vite": "^2.9.14",
"vite-plugin-dts": "^1.4.1",
"vite-plugin-html": "^3.2.0"
}
}

@@ -5,3 +5,3 @@ # debounce-search-abstraction

ℹ️ it doesn't interact with DOM. It's abstract. You feed it with a search query, and it invokes your data callbacks.
It encapsulates the debounce for your queries and skips the late results (concurrent requests).
It encapsulates debounce for your queries and skips the late results (concurrent requests).

@@ -20,6 +20,7 @@ ## Usage

type SearchResult = {
items: string[],
transformedQuery: string; // in this guide we will be transforming the input query
// usually you would want some array of resulting items here
};
// make the instance (2 important callbacks)
// create your instance (2 important callbacks)
const search = new DebounceSearch<SearchResult>({

@@ -29,16 +30,32 @@ // input reaction debounce so API requests won't go out too often as you type

// this guy makes the api request(s) to obtain and set (with callback) the search result data
async resultsProvider({ query, setResults }) {
await sleep(500); // emulating some api request here
async resultsProvider({ query, setResults, isQueryStillActual }) {
requestCallback(query);
await sleep(200); // emulating some api request here
const upperCased = query.toUpperCase(); // let's just do it uppercase
// and set the results
setResults({
items: query.split(''), // all the query chars, just for example
transformedQuery: upperCased,
});
// You may call this function as many times as you need,
// in case you want to extend (replace) with some extra source results in series
// Any set too late results will be ignored (if any input occur)
// Notice, that any late results (if user updates the query) will be skipped automatically
// So if you need any subsequent request(s) - make sure to check if our query is still actual
if (isQueryStillActual()) {
await sleep(200); // another backend request
// btw, you don't need to check query actuality before calling setResult,
// the check is already inside because it forced to skip outdated results.
// This time, let's just add a query length
// User would see the uppercase query first (setResults call above),
// and then, after 200 ms the length information would be added.
// In most real cases you would call it just once
setResults({
// let's add a query length
transformedQuery: `${upperCased} (${upperCased.length})`,
});
}
},
// and this guy applies the results (if they aren't outdated)
resultsProcessor(result) {
// note: it's called with the actual results only (late results won't get here)
console.log('RESULT', result); // render some list here
resultsProcessorCallback(result.transformedQuery);
},

@@ -48,37 +65,34 @@ // when the query is empty - you don't have to make any requests,

emptyQueryResult: () => ({
items: [],
transformedQuery: '',
}),
});
// Example
// We emulate the user typing "Hello Foobar" with some delays and then erasing the text
// [ inputDelay, char ]
const type: Array<[number, string]> = [
[100, 'h'],
[300, 'e'],
[400, 'l'],
[200, 'l'],
[400, 'o'],
[1000, ' '],
[400, 'F'],
[400, 'o'],
[300, 'o'],
[100, 'b'],
[200, 'a'],
[100, 'r'],
[1000, ''], // erasing the text
// Example scenario (from the package test)
// We emulate user typing "Hello There!" with some delays and then erasing the text back
// array items description:
// 1. input char
// 2. waiting time before typing the next char
// 3. outgoing query or null (if skipped due to debounce)
// 4. search results or null (if skipped due to updated query)
// we have a debounce set to 300 and API delays are 200 for uppercase result + 200 for length result
const scenario: Array<
[string, number, null | string, string[] | null]
> = [
['H', 300, 'H', null], // no response - it takes 300+200=500
['e', 400, 'He', null],
['l', 200, null, null],
['l', 601, 'Hell', ['HELL']], // 500 is enough to get the first response
['o', 1001, 'Hello', ['HELLO', 'HELLO (5)']], // 700 is enough to get both responses
[' ', 250, null, null], // no request, quicker than debounce
['T', 600, 'Hello T', ['HELLO T']],
['h', 300, 'Hello Th', null],
['e', 100, null, null],
['r', 200, null, null],
['e', 400, 'Hello There', null],
['!', 800, 'Hello There!', ['HELLO THERE!', 'HELLO THERE! (12)']],
['', 800, '', ['', ' (0)']],
];
let text = '';
for (const [delay, char] of type) {
await sleep(delay);
if (char) {
text += char;
} else {
text = '';
}
search.search(text);
}
// in this example resultsProcessor will be called 3 times (due to input and request delays),
// resultsProcessor will be called 3 times (due to input and request delays),
// extra inputs invalidate late results.

@@ -85,0 +99,0 @@ // Results of the following 3 queries will be given to resultsProcessor:

Sorry, the diff of this file is not supported yet