How to call function AFTER the setRest(response) sets the rest to value response.
setRest(response)
callFn(); // <-- how to call this fn synchronously after the setRest?
Is it possible using async and await functions?
With me, I will hook rest and call a function in useEffect
useEffect(() => {
callFn()
}, [rest])
Related
i have a react functional component with a signal callback
how can i access to last redux state with in it:
const Demo = ()=>{
const data = useSelectore(s=>s.items);
const dispatch= useDispatch();
const listener = (x)=>{
console.log(data);//here i need access to last state
}
signalObj.on("EventName",listener);
//== init items
useEffect(()=>{
//=== after api calls
dispatch(initItems(items));
},[])
}
in above example items state will be init after first render with api call,
should i store items in use ref, is it the way?
the best approach i found was using redux thunk,
in that you can get last state and even have async function calls
I am new to rxjs and not sure how to implement the follow logic. Any suggestion will be appreciated.
Background
I am going to implement the communication between host website and an iframe in it with postMessage. Since postMessage is one-way only, I would like to implement the logic to wait for 'response' by myself when a message is sent from host website to iframe.
I have a sync function called send(message) to invoke the postMessage to send message to iframe. Then I would like to have another function with the follow logic.
public async sendAndWait(message): Promise<responseObj> {
// 1. create an observable to wait to message event with timeout
// my first thought is as follow but I feel like it does not work
// fromEvent(window, 'message')
// .pipe(timeout(timeoutInMs))
// .subscribe(event => {
// console.info(event);
// });
// 2. run `send(message)` function
// 3. do not finish this function until timeout or receive event in the previous subscription.
}
When I use the function, I would like to have
let response = await sendAndWait(message);
Not sure if it is possible to implement? Thank you
You cannot stop code execution in JS (using Async-Await, a Promise object is returned behind the scenes. so that the code is never waiting)
Consider implementing it in the following way:
let response: responseObj;
function main(): void {
sendAndWait(MESSAGE_OBJECT).subscribe(x => response = x)
}
function sendAndWait(message): Observable<responseObj> {
send(message)
return fromEvent(window, 'message')
.pipe(
timeout(timeoutInMs),
first()
)
}
Or optionally returning Promise:
async function sendAndWait(message): Promise<void> {
send(message)
const response = await fromEvent(window, 'message')
.pipe(
timeout(timeoutInMs),
first(),
toPromise()
)
}
When using next-redux-wrapper how do I start a long asynchronous task so that it only runs on the client? I don’t want to use await on the server side since it would delay the initial page load. I’d rather set a loading flag as the task starts and show a loading indicator until it completes.
Let’s say my async operation looks like this:
function async takesLong(store) {
store.dispatch({type: “LOADING”, payload: true});
const result = await longOperation();
store.dispatch({type: “SETDATA”}, payload: data);
return store.dispatch({type: “LOADING”, payload: false});
}
I can call this in my Next page’s getInitialProps function like this:
MyPage.getInitialProps = async ({ store, isServer }) => {
const loader = takesLong(store)
if (isServer) await loader; // <-- will delay client response
return {
someprop: "some value"
};
};
This works well if the page loads on the client side. The operation starts, and my page can display a loading-spinner until the operation completes. But when started on the server side I have a long delay before the page displays at all. I’ve tried a number of approaches but can’t find one that works properly:
Starting the process on the server and not using await renders the page without the results being written to the store, so it has only set “loading” to true in the store and it never gets the data.
Passing store in my props doesn’t work - it ends up being an empty object ({ }) in the client.
Trying to run it inside my component doesn’t seem to work for a few reasons:
a) I don’t have the store object accessible in the React Component (only in getInitialProps which won’t get called on the client).
b) Even if I use actions instead of store.dispatch in the Component, when can I call it safely? I can’t do it during render since it will change the Redux state, and componentWillReceiveProps won’t get called before the first client-side render
Is there a well defined pattern for deferring a long operation to the client-side when using Next?
Do your long async task on componentDidMount, it will run only on client side.
React in SSR not runs componentDidMount lifecycle hook.
Using bound actions during componentDidMount works. Thanks to #eenagy for the suggestion. Doing things in this order seems to do what is needed:
import { bindActionCreators } from "redux";
import { setLoading, setError, setData } from "../actions";
componentDidMount() {
if (!this.props.haveData && !this.props.loading && !this.props.error) {
this.props.setLoading(true);
loadSomeData() // <-- this takes a while to complete
.then( data => {
this.props.setData(data);
this.props.setLoading(false);
})
.catch( err => {
this.props.setError(err);
this.props.setLoading(false);
});
}
}
render() {
if (this.props.loading) return (<Loading/>);
return (/*regular page*/);
}
export const mapDispatchToProps = dispatch => {
return bindActionCreators({ setLoading, setError, setData }, dispatch);
};
export default connect(mapStateToProps, mapDispatchToProps)(Component);
This way if the initial data is not already loaded (say by another page) it will get kicked off when the
component mounts and run asynchronously until the operation completes and
calls the actions in redux to cause the page to re-render.
I have a fetch instruction in one function that grabs an API key from a server and it's used by a few other objects to deliver that API key to whatever service needs it.
export default async function getAPIKey(key) {
return await (await fetch('http://localhost:8000/' + key)).json();
}
And in my weather object:
export default {
URI: 'https://api.openweathermap.org',
getLocalWeather: async function(city=null, countryCode=null) {
try {
// fetch the API key from environment
const API_KEY = await getAPIKey('wx');
//... rest of code
The code as it is works, but I don't understand why I need 3 await statements. Wouldn't I only need two? I need one for the fetch() in getAPIKey(). Then .json() returns a promise because it has to wait for the response body, so I'd need an await where I call the function in getLocalWeather(). But if I don't have two awaits in getAPIKey() it just returns [object Response]?
Essentially I'm wondering why the following is wrong:
export default async function getAPIKey(key) {
return (await fetch('http://localhost:8000/' + key)).json();
}
And in my weather object:
export default {
URI: 'https://api.openweathermap.org',
getLocalWeather: async function(city=null, countryCode=null) {
try {
// fetch the API key from environment
const API_KEY = await getAPIKey('wx');
//... rest of code
Am I miss-counting? Because I only see two Promises. I know async/await functions are promises under the hood, so getAPIKey() is a promise, but wouldn't that promise be the .json() Promise? And if so why isn't the await where I call the function sufficient?
I'm not sure what what I'm failing to understand.
You don't need any of those await statements inside of getAPIKey() and your function doesn't even need to be async. You can just do this:
export default function getAPIKey(key) {
return fetch('http://localhost:8000/' + key).json();
}
You just want to return the promise from fetch().json().
The code as it is works, but I don't understand why I need 3 await statements. Wouldn't I only need two?
Actually, you only need one when you do await getAPIKey(). The others inside of getAPIKey() are not needed at all.
When you do something like:
export default async function getAPIKey(key) {
return await fetch('http://localhost:8000/' + key).json();
}
You're just adding a superfluous await that has no benefit. The function returns a promise (all async functions return a promise) and that promise is resolved when the await is done which is exactly the same as just doing return fetch('http://localhost:8000/' + key).json(); in the first place. Adding the second await also adds no value.
promises are executed only if you call .then on them
or this is how I learned it.
Async functions are what I understand functions "turned" promises. Do I need to call .then on them each time I want to invoke an async function?
async function loadStory(){}
....
loadStory()
or
loadStory().then
Async functions are executed as per regular functions by invoking them as usual.
In order to make your code appear synchronous and utilise the benefits of async / await you'll need to prefix the call with await.
For example:
async function example () {
return new Promise(resolve => {
resolve('hello');
});
}
const myReturnedValue = await example();
Because of the await keyword, myReturnedValue will be the result of the resolved promise returned by the example function.