After searching for hours... most of example is like this...
var source = Rx.Observable.timer(0, 1000)
.takeUntil(Rx.Observable.timer(5000));
var subscription = source.subscribe(
function (x) { console.log('Next: ' + x); },
function (err) { console.log('Error: ' + err); },
function () { console.log('Completed'); })
Result
Next: 0
Next: 1
Next: 2
Next: 3
Next: 4
Completed
but, I wan to know is it possible to check from source value not another observable object.. something like this..
var source = Rx.Observable.timer(0, 1000)
.takeUntil((result) => result == 5);
I guess what you are looking for is takeWhile
var source = Rx.Observable.timer(0, 1000)
.takeWhile((result) => result < 5);
source.subscribe(
(val) => console.log(val),
(err) => console.log(err),
() => console.log('complete')
);
Related
I'm not sure what's going on here. I have set up an API route in NextJS that returns before the data has been loaded. Can anyone point out any error here please?
I have this function that calls the data from makeRequest():
export async function getVendors() {
const vendors = await makeRequest(`Vendor.json`);
console.log({ vendors });
return vendors;
}
Then the route: /api/vendors.js
export default async (req, res) => {
const response = await getVendors();
return res.json(response);
};
And this is the makeRequest function:
const makeRequest = async (url) => {
// Get Auth Header
const axiosConfig = await getHeader();
// Intercept Rate Limited API Errors & Retry
api.interceptors.response.use(
function (response) {
return response;
},
async function (error) {
await new Promise(function (res) {
setTimeout(function () {
res();
}, 2000);
});
const originalRequest = error.config;
if (error.response.status === 401 && !originalRequest._retry) {
token[n] = null;
originalRequest._retry = true;
const refreshedHeader = await getHeader();
api.defaults.headers = refreshedHeader;
originalRequest.headers = refreshedHeader;
return Promise.resolve(api(originalRequest));
}
return Promise.reject(error);
}
);
// Call paginated API and return number of requests needed.
const getQueryCount = await api.get(url, axiosConfig).catch((error) => {
throw error;
});
const totalItems = parseInt(getQueryCount.data['#attributes'].count);
const queriesNeeded = Math.ceil(totalItems / 100);
// Loop through paginated API and push data to dataToReturn
const dataToReturn = [];
for (let i = 0; i < queriesNeeded; i++) {
setTimeout(async () => {
try {
const res = await api.get(`${url}?offset=${i * 100}`, axiosConfig);
console.log(`adding items ${i * 100} through ${(i + 1) * 100}`);
const { data } = res;
const arrayName = Object.keys(data)[1];
const selectedData = await data[arrayName];
selectedData.map((item) => {
dataToReturn.push(item);
});
if (i + 1 === queriesNeeded) {
console.log(dataToReturn);
return dataToReturn;
}
} catch (error) {
console.error(error);
}
}, 3000 * i);
}
};
The issue that I'm having is that getVendors() is returned before makeRequest() has finished getting the data.
Looks like your issue stems from your use of setTimeout. You're trying to return the data from inside the setTimeout call, and this won't work for a few reasons. So in this answer, I'll go over why I think it's not working as well as a potential solution for you.
setTimeout and the event loop
Take a look at this code snippet, what do you think will happen?
console.log('start')
setTimeout(() => console.log('timeout'), 1000)
console.log('end')
When you use setTimeout, the inner code is pulled out of the current event loop to run later. That's why end is logged before the timeout.
So when you use setTimeout to return the data, the function has already ended before the code inside the timeout even starts.
If you're new to the event loop, here's a really great talk: https://youtu.be/cCOL7MC4Pl0
returning inside setTimeout
However, there's another fundamental problem here. And it's that data returned inside of the setTimeout is the return value of the setTimeout function, not your parent function. Try running this, what do you think will happen?
const foo = () => {
setTimeout(() => {
return 'foo timeout'
}, 1000)
}
const bar = () => {
setTimeout(() => {
return 'bar timeout'
}, 1000)
return 'bar'
}
console.log(foo())
console.log(bar())
This is a result of a) the event loop mentioned above, and b) inside of the setTimeout, you're creating a new function with a new scope.
The solution
If you really need the setTimeout at the end, use a Promise. With a Promise, you can use the resolve parameter to resolve the outer promise from within the setTimeout.
const foo = () => {
return new Promise((resolve) => {
setTimeout(() => resolve('foo'), 1000)
})
}
const wrapper = async () => {
const returnedValue = await foo()
console.log(returnedValue)
}
wrapper()
Quick note
Since you're calling the setTimeout inside of an async function, you will likely want to move the setTimeout into it's own function. Otherwise, you are returning a nested promise.
// don't do this
const foo = async () => {
return new Promise((resolve) => resolve(true))
}
// because then the result is a promise
const result = await foo()
const trueResult = await result()
The switch documentation on github contains an example on how to use the command.
var source = Rx.Observable.range(0, 3)
.select(function (x) { return Rx.Observable.range(x, 3); })
.switch();
var subscription = source.subscribe(
function (x) {
console.log('Next: ' + x);
},
function (err) {
console.log('Error: ' + err);
},
function () {
console.log('Completed');
});
I've tested the code at stackblitz but the output differs. Instead of
Next: 0
Next: 1
Next: 2
Next: 3
Next: 4
Completed
the console logs
Next: 0
Next: 1
Next: 2
Next: 1
Next: 2
Next: 3
Next: 2
Next: 3
Next: 4
Completed
Can somebody explain?
Now I got it. The difference in the output comes from the fact that each inner observable sequence (created by the second call to range) won't be canceled as specified by the switch-operator since each observable sequence is emitted before the next sequence has been received, i.e. the observables in that sequence complete before switch has the chance to cancel those. But if I delay the emission only the elements of the
most recent inner observable sequence
is logged to the console:
var source = Rx.Observable
.range(0, 3)
.map(x => Rx.Observable.range(x, 3).delay(1))
.switch();
var subscription = source.subscribe(
function (x) {
console.log('Next: ' + x);
},
function (err) {
console.log('Error: ' + err);
},
function () {
console.log('Completed');
});
Output:
Next: 2
Next: 3
Next: 4
Completed
I run several tests in a loop and I'd like to use a variable that is in the beforeEach on my test description
for(let i =0; i<3; i++){
describe("action", () => {
let variableToUse: string;
beforeEach(async () => {
variableToUse = await someAction(i);
});
it("some test desc " + variableToUse, async () => {
//some test using variableToUse
});
});
}
I expect the console to show "some test desc varaibleToUseValue" but the actual output is "some test desc undefined"
If I were you I would do it this way
for(let i =0; i<3; i++){
let variableToUse: string;
describe("action", () => {
beforeEach(async () => {
variableToUse = await someAction(i);
});
it("some test desc " + variableToUse, async () => {
//some test using variableToUse
});
});
}
In this case you'd be safe from reusing a value prom previous execution by accident, since it always is defined inside of a loop
let variableToUse: string;
for(let i =0; i<3; i++){
describe("action", () => {
beforeEach(async () => {
variableToUse = await someAction(i);
});
it("some test desc " + variableToUse, async () => {
//some test using variableToUse
});
});
}
This should work:
describe('testbeforeeach - ', function () {
var TestSuiteName = this.getFullName();
var TestVariable = null;
beforeEach(function () {
TestVariable = "abc";
return TestVariable;
});
it(TestSuiteName + 'Test1', function () {
console.log("TestVariable for Test1 ====", TestVariable);
});
it(TestSuiteName + 'Test2', function () {
console.log("TestVariable for Test2 ====", TestVariable);
});
});
Try below given code snippet
let variableToUse: number;
let i: number;
for(i =0; i<3; i++){
describe("action", async () => {
beforeEach(async () => {
variableToUse = i;
});
it("some test desc " + variableToUse, async () => {
//some test using variableToUse
});
});
}
How can I solve it? When I try to get a result from promise all, I get an empty array.
async function getMessage(arr) {
let response = [];
for (let count = 0; count < arr.length; count++) {
let protocol = await arr[count].link.split(':')[0];
if (protocol === 'http') {
await http.get(arr[count].link, async (res) => {
response.push(`${arr[count].link} - ${res.statusCode}\n`);
});
} else {
await https.get(arr[count].link, async (res) => {
response.push(`${arr[count].link} - ${res.statusCode}\n`);
});
}
}
return Promise.all(response)
.then((data) => {
//data === []
return data;
});
}
The await operator is used to wait for a Promise.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
I assume you're using node's native http and https module. It's true they're async functions, but they cannot be used with await straight, since they're using callback not Promise.
Afaik, you can either manually "promisify" it with util.promisify, or use some 3rd party like isomorphic-fetch which already promisified it for you.
Example:
const sayHelloWithoutPromise = () => {
setTimeout(() => console.log('hello'), 0)
}
(async function() {
await sayHelloWithoutPromise()
console.log('world!')
})()
const sayHelloWithPromise = () => {
return new Promise(r =>
setTimeout(() => r(console.log('hello')), 0)
)
}
(async function() {
await sayHelloWithPromise()
console.log('world!')
})()
I'm quite new at rxjs stuff so please be patience :).
var source = Rx.Observable.fromEvent(document, 'keyup');
source.filter(function(x){
console.log('filter with', x);
return true;
});
var subscription = source.subscribe(
function (x) {
console.log('Next: keyup!',x.keyCode);
},
function (err) {
console.log('Error: %s', err);
},
function () {
console.log('Completed');
});
whats the right way to debug inside filter
I dont see any filter with
in the console
I've also tried with
var source = Rx.Observable.fromEvent(document, 'keyup');
source.filter(function(x){
console.log('filter with', x);
return true;
});
source.do(x => console.log('do with',x));
var subscription = source.subscribe(
function (x) {
console.log('Next: keyup!',x.keyCode);
},
function (err) {
console.log('Error: %s', err);
},
function () {
console.log('Completed');
});
with no lucky
Can you give me an hint please ?
source.filter() is creating a new Observable, yet you only subscribe to the original Observable, source. Observables that aren't subscribed to are not carried out
You have to do something like this:
source.filter()
.do()
.subscribe()