If I have an asynchronous method I can put it inside a promise to force it to wait for it to be fulfilled but use it in a previous instance:
This is the example:
class meta {
obj = null;
test = () => {
return new Promise((resolve) => {
fetch('https://reqres.in/api/products/3')
.then((response) => {
this.obj = response;
resolve(true);
});
})
}
}
let mt = new meta();
mt.test().then(()=>{
console.log(mt.obj); // en este punto siempre tendra un valor la variable y puede ser usada en esta instancia.
})
Is this correct or is there a better way to do it? With this I avoid having to continue nesting code inside the fetch then ....
If I'm not mistaken, it could be simplified a little more as follows (in addition to adding a catch in case there are errors):
As I explain in this answer , you cannot "out" the result of a Promise to a previous instance . But beyond this fact, the error made by the OP in this question is quite difficult to understand when you are learning the language and its way of working, for which the answer fits.
ISSUE
You have a Class (which is nothing more than syntactic sugar of Javascript's prototype inheritance system) with asynchronous methods , in this case calls to the Fetch API .
The OP's idea is to use the result of these calls as the response of the methods of the instances of said Class, that is, objects .
However, due to the asynchronous nature of Fetch API calls, the results of these methods are not available synchronously (immediately on call) but will be available at an uncertain future time. Therefore, it is not possible to assign these results to a variable, but methods must be used
then
since the Fetch API returns Promises.The OP wonders if this is correct:
But the result of this call is as follows:
Viewing
test
the Class method:It is observed that there is indeed an assignment of a value to the property
obj
, but the value of said assignment is the result of the call tofetch
which is a called objectResponse
.Another problem with this implementation is the unnecessary use of a Promise, because
fetch
it already returns a Promise, and I don't need to wrap it in another one for it to work.Therefore, the property
obj
ofmt
, when executing the methodthen
in the call tomt.test()
, contains the objectResponse
.SOLUTION
Perhaps the OP has not fully documented the use of the Fecth API, in any case, the immediate result of a call to said API is an object, as I have already mentioned, that contains the entirety of the response received, including headers, body and so on.
This object has several methods, among which are
text()
andjson()
. The first parses ( parse ) the request body and returns a Promise containing the body in text (String
) format. The second method does the same thing but expects the request body to be formattedjson
and returns a Javascript Object constructed from thejson
body string.Assuming that we don't know in advance the type of result returned by the calling server, we can use the method
get
of the objectheaders
included in the objectResponse
that allows us to inspect the headers and in particular get the headerContent-Type
. For example:In view of the result obtained, we can use the method
json
to parse the body of the request and obtain it as a Javascript object:What the OP wants is to assign the result of the call (the body) already parsed to the property
obj
of our Class instanceMeta
. (Using uppercase Class names is good practice.) Therefore we can write the following:With this we have completed the call to the method
fetch
and we can use it in our Class in the following way:Now the code runs correctly.
In any case, for the question raised by the OP: Is this correct or is there a better way to do it? , having corrected the code, the answer is: Yes, it is correct to do it this way, that is, to access the property of the instance once the inherent asynchronous processes have been executed. However I can't tell you that there is a better way to do it because it will depend on what you need in your implementation.
A different way of doing it, which involves simply visual enhancement of the code, is by using environments of type
async
.For example, if you wrapped all your logic in a
async
self-called function, you could make use ofawait
thus avoiding the use ofthen
. Note that the methodtest()
of your Class must be declared of typeasync
in order to use itawait
with the Fetch API.For example:
Extra
Classes (introduced in ES6) are syntactic sugar for classic Javascript functions and their prototype inheritance system.
Therefore, to say that OOP works in Javascript is not, in the end, strictly true.
The introduction of the Classes, perhaps part of the fact of making the language a little more friendly with those programmers accustomed to OOP.
There is no type
Class
in Javascript, just like in other languages, so in the end a Class is just a different syntactic way of writing a function.Let's see:
As you can see, the Class is just a different way of declaring a function in Javascript.
A recommended read would be: Object Prototypes in Javascript.