sync way of using promises in nodejs - javascript

loginTest() gives me resolve(value) so it goes to .then , my problem is since promise is async code, console.log(token) gets printed with promise-pending before promise fulfills.I want to display the value only after promise is fulfilled.Can any one help ?
const token = loginTest().then(res => res).catch(err => err);
console.log(token);

Try this:
loginTest().then(res => {
console.log(res.token);
}).catch(err => err);
This presumes that the token is provided as a field of res. I don't know the structure of the response so you need to check that. Token will not be returned directly from loginTest if it is async.

Use ES6's Async / Await.
const token = await loginTest();
But please note that this line of code needs to be wrapped in a async function. Otherwise, await will not work. And note that await cannot be used in global scope.
For example:
async function getToken() {
const token = await loginTest();
// this next line will execute after the result of of loginTest() returns
console.log(token);
// do something with token after this line
const mutateToken = token + '123456';
}
Documentation of Async / Await found here: Async / Await

You could leverage Async / Await functionality:
const token = await loginTest()
console.log(token)
For Example:
async function getToken () {
const token = await loginTest()
console.log(token)
}
getToken()
You could also do the following for a "synchronous" promises way:
loginTest()
.then(res => res) // Retained for example sake of chaining promises
.then(res => console.log(res))
.catch(err => console.log(err))
This is assuming that token is res, adjust accordingly if it is an object and you need a child property :)!

Try this promise :
var loginTest = new Promise(function
(resolve, reject) {
if (isLogin) {
var login = {
username: 'admin'
//something that related with the loginTest..
};
resolve(login);
} else {
var reason = new Error('some errors..');
reject(reason);
}
})
loginTest
.then((fulfilled) => {
console.log(fulfilled);
})
.catch((error) => {
console.log(error.message);
})
so, loginTest will be printed after fulfilled, then catch error if there are some errors.

You can't access token by doing like below as it is an asyn method.
const token = loginTest().then(res => res).catch(err => err);
console.log(token);
Instead use below
loginTest().then(res => {
const token = res.token;
// your further code goes here.
}).catch(err => err);

Related

res.send() is running before async function call on express.js

Summary: creating my own API that returns epoch time, and it involves using an express.js server, but it's running res.send() before the function call. I referenced this page, but it didn't help. Here's what I have:
app.get('/timestampAPI', async (req, res,) => {
try {
let finalResult = await getTimeStamp();
res.send({ something: finalResult });
} catch (error) {
console.log(error);
}
});
It'll start to run the function getTimeStamp(), and before that function finishes, it runs the res.send() function which shows up as '{}' because finalResult doesn't have a value. getTimeStamp() is an async function. I'm unsure of what I'm doing wrong.
Edit:
getTimeStamp() function:
async function getTimeStamp() {
await axios.get('https://showcase.api.linx.twenty57.net/UnixTime/tounixtimestamp?datetime=now')
.then(response => {
// also used console.log(response.data.UnixTimeStamp), which returns the timestamp
return response.data;
})
.catch(error => {
var errorMessage = error.response.statusText;
console.log(errorMessage);
});
}
Another edit: yes, the API referenced above does return the current epoch time, but CORS is blocking my other site from accessing it directly, so I can't use it on that site, which is why I'm using node.js for it so that I can allow myself to access it through my node.js program. Couldn't think of another way
returning value of the then method does not return from getTimeStamp function you should write you code in resolve pattern or using await like below
try this, make sure you write correct field name in response object
async function getTimeStamp() {
try{
const res = await axios.get('https://showcase.api.linx.twenty57.net/UnixTime/tounixtimestamp?datetime=now')
return res.data
}catch(error){
throw error
}
As an alternative to Mohammad's answer you can also use returning getTimeStamp function's result as a promise and it can solve your problem.
async function getTimeStamp() {
return new Promise((resolve, reject) => {
axios.get('https://showcase.api.linx.twenty57.net/UnixTime/tounixtimestamp?datetime=now')
.then(response => {
// also used console.log(response.data.UnixTimeStamp), which returns the timestamp
resolve(response.data);
})
.catch(error => {
var errorMessage = error.response.statusText;
console.log(errorMessage);
reject(error);
});
})
}
Or you would also replace await with return in getTimeStamp function in your code if you don't want to return promise.(Which is not I recommend.). You should also throw the error in catch block which is generated in getTimeStamp function for catching the error in try-catch block that you use to call app.get(...).

How to handle error without crashing function with axios?

So the problem is, that in some function i want to call getRecord function. It's making request with axios. Some times request can be faild, so i want to handle the error without crashing my function, where i'm calling getRecord.
I'm calling getRecord like this:
const res = await getRecord(eventData)
console.log('handleReadyToRemoveCalls -> res', res)
Here is the getRecord function
const getRecord = ({ extTrackingId, targetId }) => {
console.log('getRecord -> executed')
const apiConfig = require('../config')
return new Promise((resolve, reject) => {
axios({
method: 'get',
url: `https://cloudpbx.beeline.ru/apis/portal/v2/records/${extTrackingId}/${targetId}/download`,
responseType: 'stream',
headers: {
'X-MPBX-API-AUTH-TOKEN': `${apiConfig.token}`,
},
})
.then((response) => {
console.log('getRecordsReference -> response', response)
resolve(response)
})
.catch((err) => {
console.log('getRecordsReference -> err', err)
reject(err)
})
})
}
With this approach i'm suddenly for me getting crashes, when request with axios fails. What's i'm doing wrong?
You are rejecting the promise in the catch block:
.catch((err) => {
reject(err)
})
Thus your propagate the error. If you want the function not to fail just return something that is not an error like an empty array. For instance:
.catch((err) => {
resolve([])
})
One other way to handle this is to reject as you do and to catch the error higher with a try catch like this:
try {
const res = await getRecord(eventData)
} catch(err){
// do whatever you want in case of an error
}
Surround with try catch.
try{
const res = await getRecord(eventData)
}catch(err){
//say dispatch a function and say please try again in UI
}
In you promise you are rejecting the with an error. That error needs to be handled in the block you are calling the function.

How to make a Javascript/React/Typescript fetch call asynchronous?

Consider the following Javascript/React code:
// Javascript function that has a fetch call in it.
export const signIn = (email:string, password:string) => {
console.log("FETCHING...");
fetch(`${endPoint}/sign_in`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email,
password
})
})
.then((response) => {
return response.json()
})
.then(({ data }) => {
console.log("FETCHED DATA...")
})
.catch((error) => {
console.error('ERROR: ', error)
})
console.log("DONE FETCHING...");
}
// A functional component that references signIn.
export const SignIn: React.FC<Props> = () => {
// irrelevant code ...
const onSubmit = (e: CustomFormEvent) => {
e.preventDefault()
console.log("SIGNING IN...")
// calls my signIn function from above
// I don't want this to finish until the fetch inside it does.
signIn(email, password, setAuthentication, setCurrentUser)
console.log("SIGNED IN...");
}
return <>A form here submits and calls onSubmit</>
}
This produces the following console log output:
SIGNING IN...
FETCHING...
DONE FETCHING...
SIGNED IN...
FETCHED DATA...
I want FETCHED DATA... to show up before DONE FETCHING.... I've tried playing around with aysnc/await but that's not working so I don't know where to go from here.
Just add another .then
.then((response) => {
return response.json()
})
.then(({ data }) => {
console.log("FETCHED DATA...")
return
}).then(()=> {
console.log("DONE FETCHING...");
})
.catch((error) => {
console.error('ERROR: ', error)
})
It would have to be in the then statements if you want the console.log to wait until the promise is resolved. Here's an example that uses async/await:
export const signIn = async (email:string, password:string) => {
console.log("FETCHING...");
const response = await fetch(`${endPoint}/sign_in`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email,
password
})
})
const data = await response.json();
console.log("FETCHED DATA...")
console.log("DONE FETCHING...");
}
You would also need to turn this into an async function if you want the console.log to happen after the data is done fetching:
const onSubmit = async (e: CustomFormEvent) => {
e.preventDefault()
console.log("SIGNING IN...")
// calls my signIn function from above
// I don't want this to finish until the fetch inside it does.
await signIn(email, password, setAuthentication, setCurrentUser)
console.log("SIGNED IN...");
}
In order to use async await, you need to return a promise from the call. So basically you don't execute the .then and wrap the call in a try catch block.
export const signIn = async (email:string, password:string) => {
console.log("FETCHING...");
return fetch(`${endPoint}/sign_in`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email,
password
})
})
}
and
const onSubmit = async (e: CustomFormEvent) => {
e.preventDefault()
console.log("SIGNING IN...")
// calls my signIn function from above
// I don't want this to finish until the fetch inside it does.
try {
const data = await signIn(email, password, setAuthentication, setCurrentUser)
// Parse data, do something with it.
console.log("SIGNED IN...");
} catch (e) {
// handle exception
}
}
You may want to look more into how promises in JavaScript works.
One problem here is in signIn. What you're doing right now is:
function signIn() {
// 1. log FETCHING
// 2. call asynchronous fetch function
// 3. log DONE FETCHING
}
The key here is that fetch is asynchronous. The program doesn't wait for it to finish before moving on. See the problem? The JavaScript interpreter is going to run step 3 without waiting for step 2 to finish.
There are multiple ways to fix this. First, you can use then. Here's an example:
promise
.then(res => func1(res))
.then(res => func2(res))
.then(res => func3(res))
Here, you're telling JavaScript to:
Run promise, and wait for it to resolve.
Take the result from promise and pass it into func1. Wait for func1 to resolve.
Take the result from func1 and pass it into func2. Wait for func2 to resolve.
etc.
The key difference here is that you are running each then block in order, waiting for each previous promise to be resolved before going to the next one. (Whereas before you didn't wait for the promise to resolve).
Your code with promises would look like:
export const signIn = (email: string, password: string) => {
console.log("FETCHING...")
// Note that we return the promise here. You will need this to get onSubmit working.
return fetch(/* args */)
.then(res => res.json())
.then(({ data }) => console.log("DONE FETCHING"))
.catch(err => /* HANDLE ERROR */)
}
The second way to fix this is to use async and await. async and await is simply syntax sugar over promises. What it does underneath is the exact same, so make sure you understand how promises work first. Here's your code with async and await:
// The async keyword here is important (you need it for await)
export const signIn = async (email: string, password: string) => {
console.log("FETCHING...");
try {
const res = await fetch(/* args */) // WAIT for fetch to finish
const { data } = res.json()
console.log("FETCHED DATA...")
} catch (err) {
/* HANDLE ERROR */
}
console.log("DONE FETCHING...")
}
There's also a second similar problem in onSubmit. The idea is the same; I'll let you figure it out yourself (the important part is that you must return a Promise from signIn).

NodeJS NPM soap - how do I chain async methods without callbacks (ie use async or Promise)?

I have successfully called a sequence of soap webservice methods using nodejs/javascript, but using callbacks... right now it looks something like this:
soap.createClient(wsdlUrl, function (err, soapClient) {
console.log("soap.createClient();");
if (err) {
console.log("error", err);
}
soapClient.method1(soaprequest1, function (err, result, raw, headers) {
if (err) {
console.log("Security_Authenticate error", err);
}
soapClient.method2(soaprequest2, function (err, result, raw, headers) {
if (err) {
console.log("Air_MultiAvailability error", err);
}
//etc...
});
});
});
I'm trying to get to something cleaner using Promise or async, similar to this (based on the example in the docs here https://www.npmjs.com/package/soap) :
var soap = require('soap');
soap.createClientAsync(wsdlURL)
.then((client) => {
return client.method1(soaprequest1);
})
.then((response) => {
return client.method2(soaprequest2);
});//... etc
My issue is that in the latter example, the soap client is no longer accessible after the first call and it typically returns a 'not defined' error...
is there a 'clean' way of carrying an object through this kind of chaining to be used/accessible in subsequent calls ?
Use async/await syntax.
const soap = require('soap');
(async () => {
const client = await soap.createClientAsync(wsdlURL);
cosnt response = await client.method1Async(soaprequest1);
await method2(soaprequest2);
})();
Pay attention to Async on both createClient and method1
In order to keep the chain of promises flat, you can assign the instance of soap to a variable in the outer scope:
let client = null;
soap.createClientAsync(wsdlURL)
.then((instance) => {
client = instance
})
.then(() => {
return client.method1(soaprequest2);
})
.then((response) => {
return client.method2(soaprequest2);
});
Another option would be nested chain method calls after the client is resolved:
soap.createClientAsync(wsdlURL)
.then((client) => {
Promise.resolve()
.then(() => {
return client.method1(soaprequest2);
})
.then((response) => {
return client.method2(soaprequest2);
});
})

How do I resolve a promise in Node.js?

I am trying to make a simple weather application based on Node.js, like this one. My problem is that every mechanism I see is based on promises, and I don't understand the concept.
So, the code I see everywhere is like:
yrno.getWeather(LOCATION).then((weather) => {
weather.getFiveDaySummary().then((data) => console.log('five day summary', data));
weather.getForecastForTime(new Date()).then((data) => console.log('current weather', data));
})
.catch((e) => {
console.log('an error occurred!', e);
});
However, I was unable to find a way to resolve these promises and save the five day summary to a variable for later use.
How do I proceed?
Thanks,
Robin
Assign the Promise returned from yrno.getWeather(LOCATION) call to a variable.
Use Promise.all() to return results from both weather.getFiveDaySummary() and weather.getForecastForTime(new Date()) calls.
Chain .then() to the result of call to get the data at initial and subsequent .then() chained to variable identifier which returned initial Promise values.
let weatherData = yrno.getWeather(LOCATION).then(weather => {
// note `return`, alternatively omit `return` and `{`, `}` at arrow function
// .then(weather => Promise.all(/* parameters */))
return Promise.all([weather.getFiveDaySummary()
, weather.getForecastForTime(new Date())]);
});
weatherData
// `results` is array of `Promise` values returned from `.then()`
// chained to `yrno.getWeather(LOCATION).then((weather)`
.then(results => {
let [fiveDaySummary, forecastForTime] = results;
console.log('five day summary:', fiveDaySummary
, 'current weather:', forecastForTime);
// note `return` statement, here
return results
})
.catch(e => {
// `throw` `e` here if requirement is to chain rejected `Promise`
// else, error is handled here
console.log('an error occurred!', e);
});
// weatherData
// .then(results => { // do stuff with `results` from first `weatherData` call })
// .catch(e => console.log(e));
An alternative to using promises directly is to use await/async.
// weather.js
const yrno = require('yr.no-forecast')({
version: '1.9', // this is the default if not provided,
request: {
// make calls to locationforecast timeout after 15 seconds
timeout: 15000
}
});
const LOCATION = {
// This is Dublin, Ireland
lat: 53.3478,
lon: 6.2597
};
async function getWeather() {
let weather = await yrno.getWeather(LOCATION);
let fiveDaySummary = await weather.getFiveDaySummary();
let forecastForTime = await weather.getForecastForTime(new Date());
return {
fiveDaySummary: fiveDaySummary,
forecastForTime: forecastForTime,
}
}
async function main() {
let report;
try {
report = await getWeather();
} catch (e) {
console.log('an error occurred!', e);
}
// do something else...
if (report != undefined) {
console.log(report); // fiveDaySummary and forecastForTime
}
}
main(); // run it
you can run this (node.js 7) with:
node --harmony-async-await weather
You can use await/async on older targets by using Babel or Typescript to transpile it down for you.
Bonus (based off your comments) - I wouldn't do it this way, but just to show you it can be done:
const http = require('http');
const port = 8080;
http.createServer(
async function (req, res) {
let report = await getWeather(); // see above
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write("" + JSON.stringify(report.fiveDaySummary));
res.end('Hello World\n');
})
.listen(port);
again with node --harmony-async-await weather or transpile it.

Categories