I am getting into callbacks(do not want to use promise and async-await right now) and wrote code in node.js to sum a, b and c where I have created three functions for getting values of a, b and c.
// getting value of a
const getA = () => 10
// getting for value b
const getB = () => 20
// This function has to wait for 2 seconds to
const getC = (callback) => {
setTimeout(() => {
callback(30)
}, 2000);
}
const sum = (a, b, c, callback) => {
callback(a + b + c)
}
sum(getA(), getB(), getC((c) => c), (sum) => console.log(sum))
I want output 60 after waiting for getC() to finish execution, but didn't get any
I really suggest to use promises. I know there are some corner cases, where you can't. Why? Because we used to think in a way that the code is linear, and it is easier to the brain to process.
But for your question I would give a solution.
// getting value of a
const getA = () => 10;
// getting for value b
const getB = () => 20;
// This function has to wait for 2 seconds to
const getC = (callback) => {
setTimeout(() => {
callback(30);
}, 2000);
};
getC((val) => console.log(getA() + getB() + val));
So you wait until getC has finished, and use the callback to consume the c result.
Related
Is it possible to assign values at runtime for below Jest test.each example:
describe('jb-tests', () => {
jest.setTimeout(700000);
let table: Array<number[][]> = [[]];
beforeAll(() => {
//Below lines are just hardcoded values
table = [];
let test = [[1,2,3],[4,5,6],[7,8,9]]
table.push(test);
});
test.each(table)('.add(%i, %i)', (a, b, expected) => {
console.log("inside");
});
});
This test case is stuck and not showing any output. If I remove the jest.setTimeout then it fails with message "Exceeded timeout of 5000 ms for a test."
Building on the comment from #jonrsharpe, you can however specify values in the test.each() call.
describe('jb-tests', () => {
jest.setTimeout(700000);
test.each([
[1,2,3],
[4,5,6],
[7,8,9],
])('.add(%i, %i)', (a, b, expected) => {
expect(a + b).toBe(Expected);
});
});
However, if you really need data from an external source, and want to process it, you can load it in the test code, or a beforeAll(). Note that the beforeAll() is evaluated at the very start, so what is loaded there is done at the start of processing the file, not as each test is run.
import * as NodeJSFS from 'fs/promises';
describe('jb-tests', () => {
jest.setTimeout(700000);
let table: Array<number[][]> = [[]];
beforeAll(async () => {
const FileContent$: Buffer = await NodeJSFSPromises.readFile('testdata.txt');
// Loop through FileContent$ (map, etc.) and load your table (table.push)
...
});
describe('adding addition describe for this section', () => {
for (const data of table) {
... // Parse data (one element of table)
it(`should add ${a} + ${b} to be ${Expected}', () => {
expect(a + b).toBe(Expected);
});
}
});
Just found an alternate solution: Populate the test data dynamically and then use describe block to execute test cases using test.each.
let test_data: Array<number[]> = [];
for(let i=0;i<3;i++){
test_data.push([i+0,i+1,i+2]);
}
describe('jb-tests', () => {
test.each(test_data)('.add(%i, %i, %i)', (a, b, c) => {
expect(a + b + c).toBeGreaterThan(0);
});
});
Iam going through one of nodejs app and can find a syntax where code is:
const deleteData = async (
param_name,
param_addr
) => {
await callRequests(post_no, card_id => () => submitData(param_name, param_addr)
);
}
Iam not pretty sure what the double '=>' means here- " => () => " in the last line. Is it kind of double arrow function?
It's an lambda (arrow function) that returns a lambda.
A concrete example:
const sortFactory = (sign) => (a, b) => (a - b) * sign
const arr = [1, 3, 4, 2]
arr.sort(sortFactory(1)) // ascending
arr.sort(sortFactory(-1)) // ascending
In this question, it's a lambda with argument card_id that returns a no-argument lambda () => submitData(param_name, param_addr)
I've got two event streams. One is from an inductance loop, the other is an IP camera. Cars will drive over the loop and then hit the camera. I want to combine them if the events are within N milliseconds of each other (car will always hit the loop first), but I also want the unmatched events from each stream (either hardware can fail) all merged into a single stream. Something like this:
---> (only unmatched a's, None)
/ \
stream_a (loop) \
\ \
--> (a, b) ---------------------------> (Maybe a, Maybe b)
/ /
stream_b (camera) /
\ /
--> (None, only unmatched b's)
Now certainly I can hack my way around by doing the good ole Subject anti-pattern:
unmatched_a = Subject()
def noop():
pass
pending_as = [[]]
def handle_unmatched(a):
if a in pending_as[0]:
pending_as[0].remove(a)
print("unmatched a!")
unmatched_a.on_next((a, None))
def handle_a(a):
pending_as[0].append(a)
t = threading.Timer(some_timeout, handle_unmatched)
t.start()
return a
def handle_b(b):
if len(pending_as[0]):
a = pending_as[0].pop(0)
return (a, b)
else:
print("unmatched b!")
return (None, b)
stream_a.map(handle_a).subscribe(noop)
stream_b.map(handle_b).merge(unmatched_a).subscribe(print)
Not only is this rather hacky, but although I've not observed it I'm pretty sure there's a race condition when I check the pending queue using threading.Timer. Given the plethora of rx operators, I'm pretty sure some combination of them will let you do this without using Subject, but I can't figure it out. How does one accomplish this?
Edit
Although for organizational and operational reasons I'd prefer to stick to Python, I'll take a JavaScript rxjs answer and either port it or even possibly rewrite the entire script in node.
You should be able to solve the problem using auditTime and buffer. Like this:
function matchWithinTime(a$, b$, N) {
const merged$ = Rx.Observable.merge(a$, b$);
// Use auditTime to compose a closing notifier for the buffer.
const audited$ = merged$.auditTime(N);
// Buffer emissions within an audit and filter out empty buffers.
return merged$
.buffer(audited$)
.filter(x => x.length > 0);
}
const a$ = new Rx.Subject();
const b$ = new Rx.Subject();
matchWithinTime(a$, b$, 50).subscribe(x => console.log(JSON.stringify(x)));
setTimeout(() => a$.next("a"), 0);
setTimeout(() => b$.next("b"), 0);
setTimeout(() => a$.next("a"), 100);
setTimeout(() => b$.next("b"), 125);
setTimeout(() => a$.next("a"), 200);
setTimeout(() => b$.next("b"), 275);
setTimeout(() => a$.next("a"), 400);
setTimeout(() => b$.next("b"), 425);
setTimeout(() => a$.next("a"), 500);
setTimeout(() => b$.next("b"), 575);
setTimeout(() => b$.next("b"), 700);
setTimeout(() => b$.next("a"), 800);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/rxjs#5/bundles/Rx.min.js"></script>
If it's possible for b values to be closely followed by a values and you do not want them to be matched, you could use a more specific audit, like this:
const audited$ = merged$.audit(x => x === "a" ?
// If an `a` was received, audit upcoming values for `N` milliseconds.
Rx.Observable.timer(N) :
// If a `b` was received, don't audit the upcoming values.
Rx.Observable.of(0, Rx.Scheduler.asap)
);
I have developed a different strategy than Cartant, and clearly much less elegant, which may give you somehow a different result. I apologize if I have not understood the question and if my answer turns out to be useless.
My strategy is based on using switchMap on a$ and then bufferTime on b$.
This code emits at every timeInterval and it emits an object which contains the last a received and an array of bs representing the bs received during the time interval.
a$.pipe(
switchMap(a => {
return b$.pipe(
bufferTime(timeInterval),
mergeMap(arrayOfB => of({a, arrayOfB})),
)
})
)
If arrayOfB is empty, than it means that the last a in unmatched.
If arrayOfB has just one element, than it means that the last a has been matched by the b of the array.
If arrayOfB has more than one element, than it means that the last a has been matched by the first b of the array while all other bs are unmatched.
Now it is a matter of avoiding the emission of the same a more than
once and this is where the code gets a bit messy.
In summary, the code could look like the following
const a$ = new Subject();
const b$ = new Subject();
setTimeout(() => a$.next("a1"), 0);
setTimeout(() => b$.next("b1"), 0);
setTimeout(() => a$.next("a2"), 100);
setTimeout(() => b$.next("b2"), 125);
setTimeout(() => a$.next("a3"), 200);
setTimeout(() => b$.next("b3"), 275);
setTimeout(() => a$.next("a4"), 400);
setTimeout(() => b$.next("b4"), 425);
setTimeout(() => b$.next("b4.1"), 435);
setTimeout(() => a$.next("a5"), 500);
setTimeout(() => b$.next("b5"), 575);
setTimeout(() => b$.next("b6"), 700);
setTimeout(() => b$.next("b6.1"), 701);
setTimeout(() => b$.next("b6.2"), 702);
setTimeout(() => a$.next("a6"), 800);
setTimeout(() => a$.complete(), 1000);
setTimeout(() => b$.complete(), 1000);
let currentA;
a$.pipe(
switchMap(a => {
currentA = a;
return b$.pipe(
bufferTime(50),
mergeMap(arrayOfB => {
let aVal = currentA ? currentA : null;
if (arrayOfB.length === 0) {
const ret = of({a: aVal, b: null})
currentA = null;
return ret;
}
if (arrayOfB.length === 1) {
const ret = of({a: aVal, b: arrayOfB[0]})
currentA = null;
return ret;
}
const ret = from(arrayOfB)
.pipe(
map((b, _indexB) => {
aVal = _indexB > 0 ? null : aVal;
return {a: aVal, b}
})
)
currentA = null;
return ret;
}),
filter(data => data.a !== null || data.b !== null)
)
})
)
.subscribe(console.log);
add.js
export default a => b => a+b;
module.js
import add from './add';
export default {
add1: n => add(1)(n),
};
test/module.js
import add from '../add';
import module from '../module';
jest.mock('../add', () => () => jest.fn());
module.add1(6);
expect(add.mock.calls).toHaveLength(1);
this can be called, but add wouldn't be a mock function, instead add() is a mock function, but the call params were not recorded correctly.
jest.mock('../add', () => () => jest.fn(a => b => a+b));
has also tried this, which doesn't seem to work correctly as well.
jest.mock('../add', jest.fn(a => b => a+b));
this would throw the inline function error
Is there a correct way to mock curry function at the moment?
Simple version should look like this
jest.mock('../add', () => (a) => jest.fn(b => a+b));
So you mock add module with a function that return that when gets called it returns the spy, problem you can't test anything on the spy.
So we need to refactor it so you have the add1 think as a spy in scope of the test
import add from '../add'
jest.mock('../add', () => jest.fn)
const addC = jest.fn()
add.mockImplemetation((a) => {
addC.mockImplementation((b => a+b)
return addC
})
I know this is a bit old but with the following answer I would have saved so much time...
import module from "./module";
const mockOperation = {
add: jest.fn()
};
jest.mock("./add", () => () => {
return mockOperation.add;
});
describe("add ", () => {
it("is called at least once", () => {
module.add1(6);
expect(mockOperation.add.mock.calls).toHaveLength(1);
});
});
A very importante thing: the constant function that you want to mock must start with the word mock. Otherwise it will throw an error.
const mockOperation = {
add: jest.fn()
};
With the mockOperation constant assigned to the add file, by reference is calling to it's add method which is a jest.fn()
I've had to do this a lot recently so I wrote a helper function to help me out.
curryMock = (baseFn, maxCurries) => {
var callIndex = 0
var curries = []
let returnFn
baseFn.mockImplementation((arg) => {
curries[callIndex] = 0
const fn = returnFn(callIndex)
callIndex++
return fn
})
returnFn = (index: number) => {
if (curries[index] < maxCurries) {
curries[index]++
return (arg: any) => {
baseFn.mock.calls[index].push(arg)
return returnFn(index)
}
}
}
}
You pass the function a jest.fn() and curryMock modifies it's implementation so that all the arguments return functions are called with will be added to the original jest.fn().mock.calls array. The second argument specifies how many times to return a function. maxCurries = 0 is for a regular function () => {},
maxCurries = 1is for a regular function() => => {}`, etc.
In your case:
import add from '../add';
import module from '../module';
jest.mock('../add');
curryMock(add)
module.add1(6);
expect(add).toHaveBeenCalledWith(1, 6);
//equivalent to
//expect(add).toHaveBeenNthCalledWith(1, 1, 6);
//if you others to test..
module.add7(4)
expect(add).toHaveBeenNthCalledWith(2, 7, 4)
curryMock is a quick utility function that I wrote for personal use. I will likely clean it up and extend it later, but I hope you get the idea: testing curried functions does not have to laborious.
I have this chain which should be concatenating 10 Observables into 1 Observable, where each of the 10 Observables should basically just be unwrapped to an integer:
const Rx = require('rxjs');
var i = 0;
const obs = Rx.Observable.interval(10)
.map(() => i++)
.map(val => Rx.Observable.create(obs => {
obs.next(val)
}))
.take(10)
.reduce((prev, curr) => {
return prev.concat(curr); // concat all observables
})
.last(val => val.flatMap(inner => inner));
// subscribe to Observable
obs.subscribe(v => {
console.log('\n next (and only) result => \n', v);
});
What's happening is that all 10 Observables should be concatenated together, but I cannot extract the values from those 10 Observables (which have become 1 Observable). So my question is, how can I unwrap that final observable and extract the value?
Anyone know what I am talking about?
This question has the exact problem as in Observable.prototype.concatAll does not seem to yield expected result
.map(function(val){ // note: map *not* flatMap
return Rx.Observable.create(obs => {
obs.next(val)
});
})
When creating your own observable using Rx.Observable.create you need to .complete() it yourself. Because you forgot to do so operators like .reduce() will not work because they need to wait for completion before being able to run.
Furthermore, your use of the .last() operator is incorrect; it takes a predicate on which your stream will be filtered and the last emission matching the predicate will be emitted. It is also a bit redundant because your .reduce() will only emit one value. Cleaning it up would lead to:
const obs = Rx.Observable.interval(10)
.map(() => i++)
.map(val => Rx.Observable.of(val))
.take(10)
.reduce((acc, curr) => acc.concat(curr))
.flatMap(v => v)
.toArray()
But you can shorten this by directly using the .concatMap() operator instead of map+take+reduce+flatMap:
const obs = Rx.Observable.interval(10)
.map(() => i++)
.concatMap(val => Rx.Observable.of(val))
.take(10)
.toArray()
Instead of reduce + last, you can use concatAll (or concatMap) to concatenate inner sequences and preserve order:
Observable
.interval(0)
.map(i => Observable.of(i))
.take(10)
.concatAll()
.takeLast(1)
.subscribe(v => console.log('\n next (and only) result => \n', v);)
edit: takeLast(1) instead of finalValue()
Use the non-prototype method.
let range = [...Array(10).keys()];
//array of 10 observables of 10 values each
let ten = range.map(i => Rx.Observable.interval(1000).map(_ => i).take(10));
let sequence = Rx.Observable.concat(ten) // all of them in sequence