Sorting and filtering with Client Side Refiner
Client Side Refiner is used to lighten the load on Transformer Refiner by sorting and filtering subsets of data on the client side.
Available from: StreamLinkTS 7.1.16+
Should I use Transformer Refiner or Client Side Refiner?
Client Side Refiner best complements Transformer Refiner when using it to sort and filter small containers with few subjects, particularly when the data is rapidly changing. This means fewer requests to the server, and quicker sort and filter operations.
Client Side Refiner is easier to customise quickly if you value being able to write custom sort and filter functions in TypeScript in the client.
Enabling Client Side Refiner
Client Side Refiner is disabled by default. To enable Client Side Refiner, pass the following arguments to StreamLinkFactory.create when creating a StreamLink instance.
var sl = StreamLink.StreamLinkFactory.create({
// This URL is an example – use the Liberator URL according to your setup.
liberator_urls: "ws://localhost:18080",
clientside_refiner_enable: true
})
Configuring Client Side Refiner
Configure Client Side Refiner by setting the following keys in the configuration object you pass to StreamLinkFactory.create. A full list of configuration-object keys can be found in the documentation for StreamLinkFactory.
- clientside_refiner_enable
-
Default:
false| Type:booleanWhen set to true, enables the Client Side Refiner and allows other arguments to take effect.
- clientside_refiner_fn_use_for
-
Default:
undefined| Type:functionIf
clientside_refiner_enableis true, this function determines if individual container subscriptions should be refined on the client or server.Returning
truefrom this function will enable Client Side Refiner for the container subject matching thesubjectparameter.Example:
Using Client Side Refiner for container subscriptions under EXAMPLES/PRICINGStreamLinkFactory.create({ // ... clientside_refiner_fn_use_for: (subject: String, parameters: SubscriptionParameters): boolean => { return subject.includes("EXAMPLES/PRICING"); } }) - clientside_refiner_custom_sorts
-
Default:
undefined| Type:objectclientside_refiner_custom_sortstakes an object consisting of key-value pairs mapping custom sort names to their sort functions.See Refiner subject syntax for how to construct subject sort parameters.
Example:
Sort items containing the text "Inc."const daysOfWeek = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']; function sortByDay(a: any, b: any): number { const dayA = daysOfWeek.indexOf(a); const dayB = daysOfWeek.indexOf(b); if (dayA < dayB) { return -1; } else if (dayA > dayB) { return 1; } else { return 0; } } var streamlink = StreamLinkFactory.create({ // ... clientside_refiner_custom_sorts: { sort_by_day: sortByDay } }); - clientside_refiner_custom_filters
-
Default:
undefined| Type:objectclientside_refiner_custom_filterstakes an object consisting of key-value pairs mapping custom filter names to their filter functions.The filter functions can be one of two types:
-
A comparator function with the signature
(fieldValue: string, filterCriterion: string): number, similar to the functions provided toclientside_refiner_custom_sorts.This type should be used when the filter expression is of the form
where:customFilterName:<fieldname>:<operator>:<value>. -
A function with the signature
(fieldProvider: IFieldProvider): boolean, wherefieldProvidercontains the methodgetField(fieldName: string): any, which is used to get a field from the record being filtered.This type should be used when the filter expression is of the form
where:x.
See Refiner subject syntax for how to construct subject filter parameters.
Examples:
Custom filter by grade (type A)const grades = ['A', 'A+', 'AA-', 'AA', 'AA+', 'AAA']; function gradeFilter(fieldValue: string, filterCriterion: string): number { const fieldValueRank = grades.indexOf(fieldValue); const filterCriterionRank = grades.indexOf(filterCriterion); if (fieldValueRank === filterCriterionRank) { return 0; } else if (fieldValueRank < filterCriterionRank) { return -1; } else { return 1; } } var streamLink = StreamLinkFactory.create({ // ... clientside_refiner_custom_filters: { grade_filter: gradeFilter } });Custom filter by a combination of fields (type B)function spreadTargetFilter(fieldProvider: { getField: (name: string) => any }): boolean { const bestAsk = Number(fieldProvider.getField("BestAsk")); const bestBid = Number(fieldProvider.getField("BestBid")); const spreadTarget = Number(fieldProvider.getField("SpreadTarget")); return bestAsk - bestBid >= spreadTarget; } var streamLink = StreamLinkFactory.create({ // ... clientside_refiner_custom_filters: { spread_target_filter: spreadTargetFilter } }); -