await http request response in constructor - javascript

I have a class, how I can create await for key value, that should be requested from http request in another method?
I don't know how to correct use await in this situation.
Here code, it returns only undefined:
class MyClass {
constructor(key = null) {
if (!!key)
this.key = key;
else
(async () => { this.key = await this.getKey(); })();
}
getKey(input) {
return new Promise((resolve, reject) => {
let options,
request,
data = '';
try {
options = {
host: '...',
port: '80',
path: '/',
method: 'GET',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};
request = http.request(options, (response) => {
response.setEncoding('utf8');
response.on('data', (chunk) => {
data += chunk.toString();
});
response.on('end', () => {
resolve(new RegExp('<div id="...".*>(.*)<\/div>', 'g').exec(data)[1]);
});
});
request.end();
} catch (error) {
reject(error);
}
});
}
}

a better usage would be to use await for the var you'll put in parameter :
let key = await getKey();
let myClass = new MyClass(key);

Perhaps I'm as confused about async await as you are, but it doesn't really seem necessary in this scenario.
class MyClass {
initKey() {
this.getKey().then(d => { this.key = d })
}
getKey(){
return new Promise((resolve, reject) => {
resolve("the promised value")
})
}
}
let t = new MyClass()
t.initKey()

Related

test http.request with options using jest

Im learning using Jest and i faced this function,
but not sure how to start testing, it has inside an http.request({}, (res) => {})
and not sure how can i mock this http.request inside the current function:
also the resolve and reject from the current promise,
in advance Thank You!
const options = {
hostname: 'myHostName'
port: 'myPort',
path: 'myPath',
method: 'GET'
};
function myRequest(options) {
return new Promise((resolve, reject) => {
const req = http.request(options, (res) => {
if (res.statusCode === 200) {
let responseData = '';
res.on('data', (data) => {
responseData += data;
});
res.on('end', () => {
const response = JSON.parse(responseData);
resolve([response, true]);
});
} else {
reject(`res.message`);
}
});
req.on('error', (error) => {
reject(error);
});
req.end();
});
}

NodeJs wait until all calls in loop are finished

I have the following code in node (beginner), I want to call a function after all the code has been executed in the loop, I know that I have to use promises, but I don't know how to apply them in this situation. The code has been simplified. Many thanks.
const axios = require('axios').default;
axios.post('url', {
params: {}
}).then(response=>{
var objResponse = response.data
Object.keys(objResponse).forEach(function (key){
axios.post('url', {
params: {}
}).then(response=>{
var n=0;
getCode(n);
})
})
**finishFunction**()
})
function getCode(n) {
axios.post('url', {
params: {}
}).then(response=>{
if(response.data){
if (response.data.code) {
getData();
}else{
if (n < 10) {
n++;
getCode(n);
} else {
getTimeout();
}
}
}
})
}
function getTimeout() {
axios.post('url', {
params: {}
})
}
function getData() {
axios.post('url', {
params: {}
}).then(response=>{
console.log('finished one loop');
})
}
Best way to achieve what you want is to use async/await with a regular for-loop.
Here is an example of what I mean. You can adjust it to your needs:
async doSomeStuff() {
const results = []
const res1 = await axios.post('url', {
params: {}
})
// assuming res1 is an Array
for (let i=0; i < res1.length; i++) {
const result = await axios.post('url2', {
params: {}
})
results.push(result)
}
return results
}
You can also call other async functions inside the loop as you are doing.
You could use Promise all and map together, alongside async/await
async function myFunction(){
const result = await axios.post('url');
const keys = Object.keys(result.data);
const requests = keys.map((key, i) => axios.post('url')/*chain more if u need*/)
const allResults = await Promise.all(requests);
// All done run your function below
}
If you are happy for each item in the loop to be run at the same time, you can use an array of promises and wait for everything in the array to finish. Then you just have to add promises to your functions which will take an unknown amount of time to run. Something like this might get you started:
const axios = require('axios').default;
axios.post('url', {
params: {}
}).then(response=>{
var objResponse = response.data
var proms = [];
Object.keys(objResponse).forEach(function (key){
proms.push(
axios.post('url', {
params: {}
}).then(response=>{
var n=0;
return getCode(n);
})
)
})
var items = Promise.all(proms);
items.then(function (results) {
// **finishFunction**()
});
})
function getCode(n) {
return new Promise(function (resolve, reject) {
axios.post('url', {
params: {}
}).then(response=>{
if(response.data){
if (response.data.code) {
getData();
}else{
if (n < 10) {
n++;
getCode(n).then(data => {
return resolve(data)
});
} else {
getTimeout().then(data => {
return resolve(data)
});
}
}
}
})
})
}
function getTimeout() {
return new Promise(function (resolve, reject) {
axios.post('url', {
params: {}
})
return resolve()
})
}
function getData() {
return new Promise(function (resolve, reject) {
axios.post('url', {
params: {}
}).then(response=>{
console.log('finished one loop');
return resolve(response)
})
})
}

Understanding HTTP function inside Alexa Skill-- JavaScript

I am currently learning how to connect my Amazon Lambda function (in js) to an API. I found the following code which works but I am new to javascript and APIs in general and am not sure what it is doing. Could someone explain to me what this function does and how it works? Thanks!
function httpGet() {
return new Promise(((resolve, reject) => {
var options = {
host: 'api.icndb.com',
port: 443,
path: '/jokes/random',
method: 'GET',
};
const request = https.request(options, (response) => {
response.setEncoding('utf8');
let returnData = '';
response.on('data', (chunk) => {
returnData += chunk;
});
response.on('end', () => {
resolve(JSON.parse(returnData));
});
response.on('error', (error) => {
reject(error);
});
});
request.end();
}));
}
Here the response object is a node.js stream, a 'push' stream in particular. (This article does a good job of explaining push/pull streams).
const request = https.request(options, (response) => {
// Your request has been successfully made and you are
// handed a response object which is a stream, which will emit
// a 'data' event when some data is available.
response.setEncoding('utf8');
let returnData = '';
// A chunk of data has been pushed by the stream,
// append it to the final response
response.on('data', (chunk) => {
returnData += chunk;
});
// All the data has been pushed by the stream.
// 'returnData' has all the response data. Resolve the
// promise with the data.
response.on('end', () => {
resolve(JSON.parse(returnData));
});
// Stream has thrown an error.
// Reject the promise
response.on('error', (error) => {
reject(error);
});
});
request.end();
I found a better solution. Create a function to getRemoteData and/or postRemoteData.
getRemoteData (url) {
return new Promise((resolve, reject) => {
axios
.get(url)
.then(res => {
console.log(res.data);
resolve(res.data);
})
.catch(error => {
console.error(error);
});
})
},
postRemoteData (url, body) {
return new Promise((resolve, reject) => {
axios
.post(url, body)
.then(res => {
console.log(res.data);
resolve(res.data);
})
.catch(error => {
console.error(error);
});
})
},
Then use these functions in your IntentsHandlers.
//Get
const url = "https://anydir.com"
let speakOutput = "No data";
await logic.getRemoteData(url)
.then((data) => {
speakOutput = data.results.toString();
})
//Post
const url = "https://anydir.com"
let speakOutput = "No data";
await logic.getRemoteData(url, {param1:valueParam1,param2:valueParam2})
.then((data) => {
speakOutput = data.results.toString();
})
Example.
const NumberCharactersIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'NumberCharactersIntent';
},
async handle(handlerInput) {
const url = "https://rickandmortyapi.com/api/character"
let speakOutput = "No data";
await logic.getRemoteData(url)
.then((data) => {
speakOutput = `There are ${data.results.length.toString()} in the Rick and Morty serie`
})
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse();
}
};

How do I return only type of resolve in a Promise?

let companyInfo: PublicCompanyAPIResponseType;
companyInfo = await get<PublicCompanyAPIResponseType>({
url: getCompanyDataURL,
}).catch(res => {
responseStatus = res.status;
});
When i assign companyInfo variable to that get func
export async function get<T>({ url, headers }: ApiConnectSet): Promise<T> {
return new Promise((resolve, reject) => {
fetch(url, {
method: 'GET',
credentials: 'same-origin',
headers: headers,
})
.then(async res => {
if (res.ok) {
return resolve((await res.json()) as Promise<T>);
} else if (res.status === 401) {
const redirectPath = window.location.pathname;
window.location.href =
'/login?redirectPath=' + redirectPath;
} else {
reject(res);
}
})
.catch(error => {
reject(error);
});
});
}
Visual studio code shows this error
How can my get function only return PublicCompanyAPIResponseType?
try this, if it works
let companyInfo: PublicCompanyAPIResponseType;
try {
companyInfo = await get<PublicCompanyAPIResponseType>({
url: getCompanyDataURL,
})
} catch(err => {
// get the status from error object and assign it to response status
responseStatus = // your status code
});
Have you tried just adding the Promise<T> in the return statement?
export async function get<T>({ url, headers }: ApiConnectSet): Promise<T> {
return new Promise<T>((resolve, reject) => {
//your code
}
);

Promise returns wrong value

In my code I try to assign a value to json variable to return it after (because I can't return it from the anon. function).
As my function is async, because it sends requests (maybe someone knows how to make it sync? I didn't plan to make it asynchronous), I've added await before the request (https.get).
I've been trying to get value from the Promise, but it's always undefined, even though I've awaited the async function.
Here's a code:
async function get_users() {
const https = require('https');
var token = '...';
var json = undefined;
await https.get('...', (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
json = JSON.parse(data)['response']['items'];
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
return json;
}
get_users().then(function(result) {
console.log(result);
});
Return a Promise and resolve it, when the end event is called, otherwise reject it in case of an error occurred:
async function get_users() {
const https = require('https');
const token = '...';
return new Promise((resolve, reject) => {
https.get('...', resp => {
let data = '';
resp.on('data', chunk => {
data += chunk;
});
resp.on('end', () => {
let json;
try {
json = JSON.parse(data)['response']['items'];
} catch (e) {
reject(e);
};
resolve(json);
});
}).on("error", err => reject(err));
});
}
get_users().then(result => console.log(result));
Please refer my below code.I had issues with getting responses from Promises too.But i finally got it to work.Here's the code:
var output;
var rp = require('request-promise-native');
var myJSONObject = {
"inputs": [{
"name": "<name>",
"value": < value >
}]
};
var orchName = 'TEST05';
postData = JSON.stringify(myJSONObject);
return networkCall(postData, orchName).then((response) => {
console.log('response is' + response)
}).catch((response) => {
console.log(`ERROR: ` + response);
});
function networkCall(postData, orchName) {
return new Promise((resolve, reject) => {
var options = {
method: 'post',
uri: '<URL>',
body: postData,
auth: {
'user': 'usr',
'pass': 'pwd'
},
json: true
};
return rp(options)
.then(body => {
var response = body;
resolve(response);
})
.catch(err => {
console.log('FAILED' + err);
reject(err);
});
});
}
This way your code can run in Synchronous Flow.If the return value is undefined,then,what might have probably happened is that the calling function would have finished executing even before the called function returns its response.But the above approach would work just fine.

Categories