Reputation: 6015
I am new to Cycle.JS. Please forgive the typescript errors as well! I'm using create-cycle-app.
I made a simple login form component. It uses the DOM and HTTP drivers. I capture the submit event from the form and map it to a credential object containing the entered username and password. I have a throttledCredential stream. It uses fold to keep track of the previous credentials and HTTP responses. It should only emit credentials if the previous event was a failed response.
I have a working throttledCredentials stream, but this took me a long time to come up with and I find it very hard to read. Is there a better way to do this?
function main(sources: Sources): Sinks {
// emits credentials whenever the the form is submitted
const credentials$: Stream<Credentials> = sources.DOM
.select('.form')
.events('submit', { preventDefault: true })
.map((e: any) => ({
username: e.target.elements.username.value,
password: e.target.elements.password.value,
}))
// maps the response onto a boolean success === true or failure === false
const response$: Stream<boolean> = sources.HTTP
.select('login')
.flatten()
.map(response => response.ok)
// can this be simplified?
const throttledCredentials$: Stream<Credentials> = xs
.merge(
credentials$.map(credentials => ({ credentials, response: null })),
response$.map(response => ({ credentials: null, response }))
)
.fold((prev: any, { credentials, response }) => {
return { credentials, cur: (credentials || response) ? true : false, prev: prev.cur }
}, { credentials: null, cur: false, prev: false })
.filter((x: any) => x.cur === true && x.prev === false)
.map(x => x.credentials)
// maps emitted credentials onto an HTTP RequestOptions to be POSTed
const request$: Stream<RequestOptions> = throttledCredentials$
.map(credentials => ({
url: 'https://reqres.in/api/login',
method: 'POST',
send: credentials,
category: 'login',
ok: () => true, // I don't know how to deal with xstream errors, so pass everything
}))
Upvotes: 0
Views: 94
Reputation: 132
I don't think to well understand your use case but you can try something like this:
function main(sources: Sources): Sinks {
// emits credentials whenever the the form is submitted
const credentials$: Stream<Credentials> = sources.DOM.select(".form")
.events("submit", { preventDefault: true })
.debug("sad")
.map((e: any) => ({
username: "username", //"[email protected]",
password: "password" //"cityslicka",
}))
.remember(); // remember the last value
// filter failed responses
const FailedResponse$: Stream<boolean> = sources.HTTP.select("login")
.flatten()
.filter(response => !response.ok);
// maps emitted credentials onto an HTTP RequestOptions to be POSTed
const request$: Stream<RequestOptions> = credentials$.map(credentials => ({
url: "https://reqres.in/api/login",
method: "POST",
send: credentials,
category: "login",
ok: () => true // I don't know how to deal with xstream errors, so pass everything
}));
// map failed response to a new request
const tryAgain$ = FailedResponse$.mapTo(request$)
.flatten()
.take(2); // here only take 2 to prevent infinite request
return {
HTTP: xs.merge(request$, tryAgain$),
DOM: xs.of(form(".form", [input(".submit", { attrs: { type: "submit" } })]))
};
}
I made a working exemple here : https://codesandbox.io/s/frosty-grass-1d5h8
I hope it's help you.
Upvotes: 1