How to clean/clear cache of a SubjectReplay instance in rxjs? - stream

I have a SubjectReplay and I would like to reset it to no cache values so after this reset the next subscriber doesn't get the history?
Example
new subject replay
subject.next(1)
reset subject <- this question
subject.subscribe() // should NOT receive 1
how can I do this? I need the subject to be the same instance.

You may look at using a combination of special values and filter operator to get something close to what you are trying to achieve.
Let's make a simple case.
You want to replay just the last value and null is the special value representing the reset. The code would be
const rs = new ReplaySubject<any>(1); // replay the last value
const rsObs = rs.asObservable().pipe(filter(d => d !== null));
rs.next(1);
rs.next(2);
setTimeout(() => {
console.log('first subscription');
rsObs.subscribe(console.log) // logs 2 on the console
}, 10);
setTimeout(() => {
rs.next(null);
}, 20);
setTimeout(() => {
console.log('second subscription');
rsObs.subscribe(console.log) // nothing is logged
}, 30);

The best way that comes to my mind with your requirement
I need the subject to be the same instance
would be to have the following observables:
// This is your input
const source$: Observable<T>;
const proxy$ = new ReplaySubject<T>(n);
const reset$ = new BehaviorSubject<number>(0);
Now it's important that we hook up the following before you emit on source$:
source$.pipe(timestamp()).subscribe(proxy$);
Then, finally, you can expose your data like this:
const data$ = proxy$.pipe(
withLatestFrom(reset$),
filter(([timedItem, resetTimestamp]) => timedItem.timestamp > resetTimestamp),
map(([timedItem]) => timedItem.value),
);
You can now use reset$.next(+new Date()) to trigger the reset.
If you can make sure to provide timestamped values to source$, you can skip the proxy$.

Related

how to get live query other spreadsheet with fastest way?

The job process is like below:
Use column A as a condition to query the spreadsheet DATA, and return the column * of the spreadsheet DATA.
But now my spreadsheet is facing the delay issue and lag problem ,
i have confuse how to settle it.
if is any wrong please forgive me
please check out the example sheets any suggestion is welcome,
and thanks at all
I believe your goal is as follows.
You want to reduce the process cost for retrieving your goal.
In your situation, how about using Google Apps Script as a direction? I thought that when Google Apps Script is used, the process cost might be able to be reduced. When Google Apps Script is used for your situation, it becomes as follows.
Sample script:
Please copy and paste the following script to the script editor of Google Spreadsheet and save the script. And, when you use this script using your provided Spreadsheet, please put a custom function of =SAMPLE('INPUT COL B'!B2:B,'DATA'!W2:AF) to a cell. By this, the result is returned.
function SAMPLE(srcValues, dataValues) {
const obj = dataValues.reduce((o, [w, ...v]) => {
const last = v.pop();
if (v.join("") != "") {
v.forEach(c => {
if (!o[c]) o[c] = [w, last];
});
}
return o;
}, {});
return srcValues.map(([b]) => obj[b] || [null, null]);
}
Testing:
When this script is for your provided Spreadsheet, the following result is obtained.
Note:
When the data becomes larger, the custom function might not be able to be used. At that time, please run the script by the script editor, custom menu, a button on Spreadsheet, and so on. The script is as follows. In this case, please copy and paste the following script to the script editor of Spreadsheet and save the script. And please run the function with the script editor. By this, in this script, the result value is put to the column "E" of "INPUT COL B" sheet.
function myFunction() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const [srcSheet, dataSheet] = ["INPUT COL B", "DATA"].map(s => ss.getSheetByName(s));
const srcValues = srcSheet.getRange("B2:B" + srcSheet.getLastRow()).getValues();
const dataValues = dataSheet.getRange("W2:AF" + dataSheet.getLastRow()).getValues();
const obj = dataValues.reduce((o, [w, ...v]) => {
const last = v.pop();
if (v.join("") != "") {
v.forEach(c => {
if (!o[c]) o[c] = [w, last];
});
}
return o;
}, {});
const res = srcValues.map(([b]) => obj[b] || [null, null]);
srcSheet.getRange(2, 5, res.length, res[0].length).setValues(res);
}
Reference:
Custom Functions in Google Sheets

Svelte array of springs

Using svelte motion I need to create an array of springs for various objects.
import { spring, type Spring } from 'svelte/motion';
.
.
.
let coords: Array<Spring<{ x: number; y: number }>> = [];
for (let i = 0; i < foo.length; i++) {
coords.push(
spring(
{ x: 50, y: 0 },
{
stiffness: 0.1,
damping: 0.1
}
)
);
}
Now when I use it in inline style
<img alt="eggs" src="./spam"
style="transform: translate({$coords[j].x}px,{$coords[j].y}px)"
/>
I get the following error-
'coords' is not a store with a 'subscribe' method
Error: 'coords' is not a store with a 'subscribe' method
No overload matches this call.
Overload 1 of 2, '(store:SvelteStore<any>):any' gave the following error.
Argument of type 'Spring<{x:number; y:number;}>[]' is not assignable to the parameter of type 'SvelteStore<any>'.
Property 'subscribe' is missing in type 'Spring<{x:number; y:number;}>[]' but is required in type 'SvelteStore<any>'.
Overload 2 of 2, '(store:SvelteStore<any> | null |undefined ):any' gave the following error.
Argument of type 'Spring<{x:number; y:number;}>[]' is not assignable to the parameter of type 'SvelteStore<any>'.
How do I solve this without creating a custom store.
A $storeVar variable will only work for a store declared in a top-level variable. If you only need access to one of those stores, you could have a line like this in your <script>:
$: myCoords = coords[j];
and then $myCoords.x and $myCoords.y will work as you'd expect.
If you need to subscribe to every store in an array, you'll need to manage the subscriptions yourself. It's not hard, but you'll need to ensure every subscription gets unsubscribed at the appropriate time.
import { onDestroy } from "svelte";
let storeValues = [];
for ( let [i, store] of coords.entries() ) {
let unsubscribe = store.subscribe( (value) => {
storeValues[i] = value; // Svelte makes this reactive
} );
onDestroy( unsubscribe );
}

Get information from Yahoo Finance

I want to get the Market Cap value from this site using importxml:
https://finance.yahoo.com/quote/KIT.OL?p=KIT.OL&.tsrc=fin-srch
Where it says 3.217B.
I am using this to get the "previous close" value:
=ImportXML("https://sg.finance.yahoo.com/quote/"&B3&"/history?p="&B3; "//tbody/tr[1]/td[6]")
I was hoping I could just adjust the above formula to get te market cap value. Anyone who can help?
Thanks!
try:
=INDEX(IMPORTXML(A1, "//tr"), 9, 2)
or:
=INDEX(QUERY(TO_TEXT(IMPORTXML(A1, "//tr")),
"select Col2 where Col1 = 'Market Cap'", 0))
however!
this way you can get only the old value. to get the new one you will need to use a script:
function YAHOO(url) {
const res = UrlFetchApp.fetch(url, {muteHttpExceptions: true});
const tables = [...res.getContentText().matchAll(/(<table[\w\s\S]+?<\/table>)/g)];
if (tables.length < 2) return "No tables. Please confirm URL again.";
const values = tables.reduce((ar, [,table]) => {
if (table) {
const root = XmlService.parse(table).getRootElement();
const temp = root.getChild("tbody", root.getNamespace()).getChildren().map(e => e.getChildren().map(f => isNaN(f.getValue()) ? f.getValue() : Number(f.getValue())));
ar = ar.concat(temp);
}
return ar;
}, []);
return values[0].map((_, i) => values.map(r => r[i]));
}
and formula:
=INDEX(YAHOO(A1), 2, 9)
extra reading: https://stackoverflow.com/a/65914858/5632629
You could try using the full XPath:
=IMPORTXML(A1,"/html/body/div[1]/div/div/div[1]/div/div[3]/div[1]/div/div[1]/div/div/div/div[2]/div[2]/table/tbody/tr[1]/td[2]/span")
Or you could try a vlookup():
=vlookup("Market Cap", IMPORTXML(A1,"//tr"),2,0)

How to modify a functions internal variables at runtime and pass it to another function?

Functions in Dart are first-class objects, allowing you to pass them to other objects or functions.
void main() {
var shout = (msg) => ' ${msg.toUpperCase()} ';
print(shout("yo"));
}
This made me wonder if there was a way to modify a function a run time, just like an object, prior to passing it to something else. For example:
Function add(int input) {
return add + 2;
}
If I wanted to make the function a generic addition function, then I would do:
Function add(int input, int increment) {
return add + increment;
}
But then the problem would be that the object I am passing the function to would need to specify the increment. I would like to pass the add function to another object, with the increment specified at run time, and declared within the function body so that the increment cannot be changed by the recipient of the function object.
The answer seems to be to use a lexical closure.
From here: https://dart.dev/guides/language/language-tour#built-in-types
A closure is a function object that has access to variables in its
lexical scope, even when the function is used outside of its original
scope.
Functions can close over variables defined in surrounding scopes. In
the following example, makeAdder() captures the variable addBy.
Wherever the returned function goes, it remembers addBy.
/// Returns a function that adds [addBy] to the
/// function's argument.
Function makeAdder(int addBy) {
return (int i) => addBy + i;
}
void main() {
// Create a function that adds 2.
var add2 = makeAdder(2);
// Create a function that adds 4.
var add4 = makeAdder(4);
assert(add2(3) == 5);
assert(add4(3) == 7);
}
In the above cases, we pass 2 or 4 into the makeAdder function. The makeAdder function uses the parameter to create and return a function object that can be passed to other objects.
You most likely don't need to modify a closure, just the ability to create customized closures.
The latter is simple:
int Function(int) makeAdder(int increment) => (int value) => value + increment;
...
foo(makeAdder(1)); // Adds 1.
foo(makeAdder(4)); // Adds 2.
You can't change which variables a closure is referencing, but you can change their values ... if you an access the variable. For local variables, that's actually hard.
Mutating state which makes an existing closure change behavior can sometimes be appropriate, but those functions should be very precise about how they change and where they are being used. For a function like add which is used for its behavior, changing the behavior is rarely a good idea. It's better to replace the closure in the specific places that need to change behavior, and not risk changing the behavior in other places which happen to depend on the same closure. Otherwise it becomes very important to control where the closure actually flows.
If you still want to change the behavior of an existing global, you need to change a variable that it depends on.
Globals are easy:
int increment = 1;
int globalAdder(int value) => value + increment;
...
foo(globalAdd); // Adds 1.
increment = 2;
foo(globalAdd); // Adds 2.
I really can't recommend mutating global variables. It scales rather badly. You have no control over anything.
Another option is to use an instance variable to hold the modifiable value.
class MakeAdder {
int increment = 1;
int instanceAdd(int value) => value + increment;
}
...
var makeAdder = MakeAdder();
var adder = makeAdder.instanceAdd;
...
foo(adder); // Adds 1.
makeAdder.increment = 2;
foo(adder); // Adds 2.
That gives you much more control over who can access the increment variable. You can create multiple independent mutaable adders without them stepping on each other's toes.
To modify a local variable, you need someone to give you access to it, from inside the function where the variable is visible.
int Function(int) makeAdder(void Function(void Function(int)) setIncrementCallback) {
var increment = 1;
setIncrementCallback((v) {
increment = v;
});
return (value) => value + increment;
}
...
void Function(int) setIncrement;
int Function(int) localAdd = makeAdder((inc) { setIncrement = inc; });
...
foo(localAdd); // Adds 1.
setIncrement(2);
foo(localAdd); // Adds 2.
This is one way of passing back a way to modify the local increment variable.
It's almost always far too complicated an approach for what it gives you, I'd go with the instance variable instead.
Often, the instance variable will actually represent something in your model, some state which can meaningfully change, and then it becomes predictable and understandable when and how the state of the entire model changes, including the functions referring to that model.
Using partial function application
You can use a partial function application to bind arguments to functions.
If you have something like:
int add(int input, int increment) => input + increment;
and want to pass it to another function that expects to supply fewer arguments:
int foo(int Function(int input) applyIncrement) => applyIncrement(10);
then you could do:
foo((input) => add(input, 2); // `increment` is fixed to 2
foo((input) => add(input, 4); // `increment` is fixed to 4
Using callable objects
Another approach would be to make a callable object:
class Adder {
int increment = 0;
int call(int input) => input + increment;
}
which could be used with the same foo function above:
var adder = Adder()..increment = 2;
print(foo(adder)); // Prints: 12
adder.increment = 4;
print(foo(adder)); // Prints: 14

How to get the last item added to firebase cloud functions realtime database

I have a simple realtime firebase db with the following structure
notification:
100000
info: "this is my info0"
100001
info: "this is my info1"
100002
info: "this is my info2"
I need to read the info in the last child and have this function in index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.helloWorld =
functions.database.ref('/notification').onWrite((snapshot, context) => {
const myData = context.info;
console.log('data: '+myData);
});
but the console log give me an error:
helloWorld
Function returned undefined, expected Promise or value
and I hope to get in the console: data: this is my info2
what is wrong in my code?
thanks!
UPDATE:
to read the last value i need to change
const myData = context.info;
to:
const myData = snapshot.after.val();
You need to return something in the trigger function. null are acceptable. If you want to get the last child everywhen you create, use onCreate instead of onWrite. The doc said:
onCreate(), which triggers when new data is created in the Realtime Database.
You maybe want to check this example: example
i need to change from:
const myData = context.info;
to:
const myData = snapshot.after.val();
then i get the last item value.

Resources