I have 2 modules in Nest.js let's call them Module1 and Module2. Module1 has an endpoint of /api/module1 and Module2 has /api/module2. I am trying to call Module2 from Module1 as below
return await this.httpService
.post(url, data1, {
headers: header
})
.pipe(
map(res => {
return res.data;
}),
);
Here the url is /api/module2 and data1 is the parameter i'm passing. When I make the call, this is what I see
{"_isScalar":false,"source":{"_isScalar":false},"operator":{}}
I usually see this error when a promise is returned before it's fully done. Not sure what to do differently here. The method which is holding this httpService called is enclosed inside an async and the calling method has an await as well.
What you're seeing there is a raw observable that hasn't been subscribed to, probably due to returning a promise instead of returning the observable. Nest's HttpService uses RxJS instead of async/await by default, but to fix this you can easily add a .toPromise() after the RxJS object and not worry about the subscription yourself.
As a side note: any reason to call the API via the HTTP module and not just call the service with the proper values directly? Seems like a lot of overhead for a REST call.
Related
Problem
I am currently working on UI and I use React. Inside of the .jsx component, I have everything : HTML (JSX), JavaScript-Logic, and API calls. Everything in one file, this gets messy.
Goal
I would like to outsource functionality, so I created a class that should handle all API-Calls. I also would like to use RxJS and combine axios with RxJs.
Code
What is happening in the the code? I have a class ApiCalls that contains a static method putApiCallExample. There I do the api call but creating a Promise with axios. I use the from() functionality form rxjs to create an observable and inside the pipe i return the data.
In the Main.jsx I am using this in the useEffect()-hook, I subscribe on it and set the State based on it.
class ApiCalls:
static putApiCallExample(URL, data){
const promise = axios
.put(URL, data, {
headers: {
"Content-Type": "application/json"
}
});
return from(promise).pipe(map(res => res.data));
}
const Main = () => {
const [show, setShow] = useState(false);
useEffect(() => {
ApiCalls.putApiCallExample().subscribe(
res => {
console.log("1", res);
setShow(true);
},
err => {
console.log("2", err)
}
);
}, [])
}
Question
Can I interpet the subscribe() functionality as same as .then() from axios ?
Do I need to unsubscribe here?
Does this cause performance issues to mix axios and rxjs?
I assume that if you use Axios, you don't need to receive multiple response from the server like for SSE or websocket. So:
Can I interpet the subscribe() functionality as same as .then() from axios ?
In a way, yes, the observable subscribe callback is triggered when Axios promise resolves. Then it will not be triggered anymore, so in this specific case, the RxJs observable behaves the same way as the Axios promise.
Do I need to unsubscribe here?
As the Observable can't be triggered more than 1 time, I don't see any reason to unsubscribe.
Does this cause performance issues to mix axios and rxjs?
You're only wrap Axios promise into a RxJs observable. This RxJs wrapper will not have a significant memory or CPU blueprint.
By the way, this is basically what's Angular Http client is doing internally. My opinion is that it's safe, but it doesn't bring too much value either.
I am building off of a forked React app. There is a dependency module that relies on a couple of static json files to map and export a couple of consts that are consumed in the app's React components. Instead of relying on these static json files, we're using an API as our source. Right now my build process is to fetch the json and transform it to generate our custom json files, which then gets consumed during the build process.
Instead, I want the process to be performed client side.
export const GALAXY = async () => {
const result = await fetch(JSON
, {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
if (result.ok) {
console.log('GALAXY LOADED')
return result.json();
} else {
console.log('GALAXY FAILED')
return undefined
}
}
It seems that anything that relies on an async/await function will only return a Promise. From the docs:
Return resolved promise from async function
Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.
Most of the examples I've found show some variation of the .then pattern:
const galaxy = Promise.resolve(GALAXY()).then((value) => {
console.log(value);
});
but if I try
const galaxy = Promise.resolve(GALAXY()).then((value) => {
return value
});
console.log(galaxy);
I get Promise{pending}
I'm hoping to avoid rewriting a bunch of non-async code. We've got one TS file that gets imported by a number of React components:
import TokenMints from './token-mints.json';
export const TOKEN_MINTS: Array<{
address: PublicKey;
name: string;
}> = TokenMints.map((mint) => {
return {
address: new PublicKey(mint.address),
name: mint.name,
};
});
So how can I fetch from the JSON API and pass the data to this non-async const so that it can be used in the rest of the app?
If you have something like this:
const example = async () => {
return true
}
Then anywhere you call it or use it will result in a promise, that's how async works.
example().then(() => {
// any code here will execute after the promise resolved
}
// any code here can not directly use the promise data as it's not resolved yet.
The code inside then and outside then will execute in parallel, or at least the code outside it will continue executing while the promise resolves and once it finally resolves it will execute the code inside the then.
Alternatively you can use await.
const data = await example() // this forces all code execution to wait for the promise to resolve
// code here will not execute until that promise resolved
You have to correctly use async/await.
Several possibilities to consider
Fetch the JSON using a synchronous XMLHttpRequest operation. Use of this kind of synchronous requests in the main thread is, however, frowned upon (note).
Convert the JSON to JavaScript source on the server (if required, in many/most cases JSON is valid JavaScript), assign it to a global variable and include it in the head section of the client page using <script> tags.
A variation of (2): convert the JSON to a module file on the server which exports the JSON data converted to JavaScipt source, which client code includes as a module, and from which imports the data as a JavaScript object.
If the client code uses the data after waiting for an event such as DOMContentLoaded (then calling a main function rather than writing the app in file level code), you could promisify the DomContentLoaded event arrival, and pass it through Promise.all along with the galaxy promise before calling main, along the lines of
Promise.all(
new Promise( resolve=>
document.addEventListener("DOMContentLoaded", resolve)
),
galaxy
).then( data => main( data[1])); // passing galaxy value
About async
As already noticed, async functions return a promise for the value syntactically returned in the function body - because async functions return synchronously when called, without waiting for any asynchronous operations performed in the function body to complete. Given JavaScript is single threaded, the caller is not put on hold until all operations have been carried out, and must return to the event loop for other pieces of JavaScript code to execute.
I'm building a game using Angular which has the following mechanics:
An Angular service checks the game state and requests a required user interaction.
A mediator service creates this request and emits it to the relevant Angular component using a RxJS subject.
A response to this request is awaited in this mediator service, game doesn't go on until request is resolved.
The component sets the user's response to the request through a call of request.respond(response) method.
I needed to come up with a Request class suitable for this requirements. As requests are resolved once and for all, I decided to avoid basing it on RxJs Observable, and tried using JavaScript Promise instead. Promises can be easly awaited with async/await syntax, and requirement (4) led me to find out about the Deferred pattern. I built this base class for all kinds of requests:
abstract class Request<T> {
private _resolve: (value: T) => void = () => {};
private _response: Promise<T> = new Promise<T>(resolve => {
this._resolve = resolve;
});
public get response(): Promise<T> {
return this._response;
}
public respond(response: T) {
this._resolve(response);
}
}
I didn't add rejection handling since I didn't come up with a situation when the request could fail. Not even a timeout seems to be needed, since the game requires a response to continue.
This worked perfectly for my purposes, but then I started to find discussions treating this as an anti-pattern (for example,this and this). I'm not used to working with promises, so I don't fully understand the risks of exposing the resolve function, I can't discern situations when this pattern would be legitimate, nor can I imagine some other way to meet my requirements using Promise.
I would like to know then if this is a legitimate way to use the Deferred pattern, and in case it is not, if there is another way to achieve what I need.
The problem of the deferred antipattern is not in exposing the resolve function in itself, but in exposing it together with (or worse, as part of) the promise. There's no reason your request class would need to contain the promise. Instead, all you need to do is simply
const response = await new Promise(resolve => {
mediator.send({ respond: resolve });
});
The mediator needs nothing but this object, and the component that handles the request can still simply call request.respond(response). This is much simpler than doing
const request = new Request();
mediator.send(request);
const response = await request.response;
This might be unnecessarily complicated (with all the code in the Request class), but the usage is not problematic yet. Where it really becomes an antipattern is if you did
function sendRequest() {
const request = new Request();
mediator.send(request);
return request;
}
because now someone has a "deferred object", not just a promise for the response. They might abuse the function:
const request = sendRequest();
request.respond("Ooops");
const response = await request.response;
This is the actual danger: returning a deferred to code that is not supposed to resolve the promise. It's totally fine to hand the resolve function to the component that is supposed to respond though.
I have created a web server i node.js using express and passport. It authenticates using an oauth 2.0 strategy (https://www.npmjs.com/package/passport-canvas). When authenticated, I want to make a call such as:
app.get("/api/courses/:courseId", function(req, res) {
// pass req.user.accessToken implicitly like
// through an IIFE
createExcelToResponseStream(req.params.courseId, res).catch(err => {
console.log(err);
res.status(500).send("Ops!");
});
});
My issue is that i would like, in all subsequent calls from createExcelToResponseStream, to have access to my accessToken. I need to do a ton of api calls later in my business layer. I will call a method that looks like this:
const rq = require("request");
const request = url => {
return new Promise(resolve => {
rq.get(
url,
{
auth: {
bearer: CANVASTOKEN // should be req.user.accessToken
}
},
(error, response) => {
if (error) {
throw new Error(error);
}
resolve(response);
}
);
});
};
If i try to create a global access to the access token, i will risk
race conditions (i think) - i.e. that people get responses in the context of another persons access token.
If i pass the context as a variable i have to refactor a
lof of my code base and a lot of business layer functions have to
know about something they don't need to know about
Is there any way in javascript where i can pass the context, accross functions, modules and files, through the entire callstack (by scope, apply, bind, this...). A bit the same way you could do in a multithreaded environment where you have one user context per thread.
The only thing you could do would be
.bind(req);
But that has has to be chained into every inner function call
somefunc.call(this);
Or you use inline arrow functions only
(function (){
inner=()=>alert(this);
inner();
}).bind("Hi!")();
Alternatively, you could apply all functions onto an Object, and then create a new Instance:
var reqAuthFunctions={
example:()=>alert(this.accessToken),
accessToken:null
};
instance=Object.assign(Object.create(reqAuthFunctions),{accessToken:1234});
instance.example();
You could use a Promise to avoid Race conditions.
Let's have this module:
// ContextStorage.js
let gotContext;
let failedGettingContext;
const getContext = new Promise((resolve,reject)=>{
gotContext = resolve;
failedGettingContext = reject;
}
export {getContext,gotContext, failedGettingContext};
And this inititalization:
// init.js
import {gotContext} from './ContextStorage';
fetch(context).then(contextIGot => gotContext(contextIGot));
And this thing that needs the context:
// contextNeeded.js
import {getContext} from './ContextStorage';
getContext.then(context => {
// Do stuff with context
}
This is obviously not very usable code, since it all executes on load, but I hope it gives you a framework of how to think about this issue with portals... I mean Promises...
The thing that happens when you call the imported 'gotContext', you actually resolve the promise returned by 'getContext'. Hence no matter the order of operations, you either resolve the promise after the context has been requested setting the dependent operation into motion, or your singleton has already a resolved promise, and the dependent operation will continue synchronously.
On another note, you could easily fetch the context in the 'body' of the promise in the 'ContextStorage' singleton. However that's not very modular, now is it. A better approach would be to inject the initializing function into the singleton in order to invert control, but that would obfuscate the code a bit I feel hindering the purpose of the demonstration.
export function postRegister(credentials) {
console.log(credentials);
return dispatch => {
return fetch('/user/register', {
method: 'post',
body: JSON.stringify(credentials),
headers: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
}
}
I have few doubts regarding code above.
Can I use export () => {} instead of writing the word function here? Just to stay cleaner.
dispatch is a global variable? I did not see it's imported or required somewhere in the file.
Is specifying headers necessary here? I'm seeing that in every of the api call.
Why there's no catch in this promise call? Overall the code is bad?
No really, you could but you need a name to actually use it in your components.
No, dispatch is a parameter of the arrow function, you can also define getState to access the current redux state. By the way, you can totally assign new names if you want.
It depends on your server, but generally if you are using a JSON API, you would want to send that header.
Yes, overall that code doesn't look good, I would recommend using a middleware to handle the fetch requests, your actions should only send the configurations such as the url, body, method, etc... and your middleware should handle adding common headers (such as the content-type).
You could have an action like this:
export function postRegister(credentials) {
return {
types: [REGISTER, REGISTER_SUCCESS, REGISTER_FAIL],
promise: {
url: '/user/register',
data: credentials,
},
};
}
Something as simple as that, then your middleware should do the fetch and dispatch the action types based on the server response.
If you want to know more about how the middleware should handle the fetch request and dispatch the actions, make sure to take a look at my post here: https://stackoverflow.com/a/39971763/146718
not unless it is export default. since later u will need to import it by name.
no, dispatch is an argument that is passed to your function:
(dispatch) => {}
Totally depends on your application, server, request, etc.
you could add .catch((e) => {}) your self, or use some interceptors for generic errors, do a dipatch from there and add a reducer which will handle these actions. you could read more here:
What is the best way to deal with a fetch error in react redux?