Have a problem with nodejs, https.request returns <http.ClientRequest>
const checkStatus = await https
.request(
{
method: 'HEAD',
host: 'host',
path: 'path',
},
(response) => {
const { statusCode } = response;
// idk
},
)
.on('error', (e) => {
if (e) {
throw new Error();
}
})
.end();
Can i somehow return statusCode instead <http.ClientRequest> inside checkStatus variable?
You can only usefully await a promise but https.request does not return a promise.
Either:
Wrap it in a new Promise or
Replace it with a library which supports promises by default (such as Axios or node-fetch)
(async function () {
const url = "https://jsonplaceholder.typicode.com/todos/1";
const response = await axios.head(url);
console.log(response.status);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js"></script>
Related
I've a problem with Axios and foreach loop. My Api provider support only 5 contemporary call so I want call one by one but when execute this code the each body not wait the the finish call function and receive the error code 429. How can resolve this? thanks.
async function call(url) {
var options = {
method: 'GET',
url: url,
auth: {
username: '*****',
password: '*****'
}
};
var response = await axios.request(options);
print(response.data["Id"])
}
app.get('/save', async (req, res) => {
var options = {
method: 'GET',
url: 'getListUser',
auth: {
username: '***',
password: '***'
}
};
var response = await axios.request(options);
response.data["users"].forEach( async (val) => {
console.log("ENTER");
var url = 'getDetailUser' + val["id"];
var res = await call(url); // <- How to wait finish this?
console.log("EXIT")
}, (err) => {
console.log(err)
})
res.status(200).send("ok").end();
});
FYI, Promise couldn't work with loop that involves callback ie forEach. Alternatively, you could use for of
try {
for (const val of response.data['users']) {
console.log("ENTER");
var url = 'getDetailUser' + val["id"];
var res = await call(url);
console.log("EXIT")
}
} catch (error) {
console.log(error)
}
I would say answer by #Ifaruki is correct with a minor change
await Promise.allSettled(response.data["users"].map(val => {
var url = 'getDetailUser' + val["id"];
return call(url);
}))
For details check the difference. In some cases Promise.all might work but if any of the Promise fails, the whole result of Promise.all will be a rejection.
The code 429 can be resolved by looking at 429 Too Many Requests
Promise.all() is the way
await Promise.all(response.data["users"].map(val => {
var url = 'getDetailUser' + val["id"];
return call(url);
}))
I am trying to test my REST APIs using Mocha and Chai.
Below is code snippet
"use strict"
// all required varibles modules declaration
describe("Get Data", function () {
it("Get Final Data", function () {
return getFinalResponse(
"https://localhost/getdata",
"GET",
JSON.stringify(rawdata)
)
.then((response) => response)
.then(async (response) => {
console.log(response)
let jsonData = await response.json()
operationId = jsonData.operation
console.log(jsonData.operation)
})
})
})
function delay(t) {
return new Promise((resolve) => setTimeout(resolve, t))
}
async function restCall(url, method, data) {
const signer = new common.DefaultRequestSigner(provider)
const httpRequest = {
uri: url,
headers: new Headers(),
method: method,
body: data,
}
await signer.signHttpRequest(httpRequest)
const response = await fetch(
new Request(httpRequest.uri, {
method: httpRequest.method,
headers: httpRequest.headers,
body: httpRequest.body,
})
)
return response
}
async function getFinalResponse(url, method, data) {
let response
do {
await delay(10000)
response = await restCall(url + "/done", method, data)
} while ((await response.json()["status"]) !== "DONE")
return restCall(url, method)
}
The condition while(await response.json()["status"] !== 'DONE') breaks/terminates in 1 minutes but even after putting 2 minutes as mocha time out . I am not getting the expected output.
Kindly help me what might be the issue.
I am trying to create an async lambda function that makes a http Get call put it's not working correctly and I believe it has to do with it being async. If I remove await/async, and make it synchronous, my function works correctly. I'm not sure what I am doing wrong. Thank you for your help!
exports.handler = async function (event, context) {
await setBattery();
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
async function setBattery() {
'use strict';
const https = require('https');
const options = {
hostname: 'testsite.com',
port: 443,
path: '/proxy/api/setting?EM_OperatingMode=1',
method: 'GET',
headers: {
'Content-Type': 'application/json',
}
};
const req = https.request(options, res => {
console.log(`statusCode: ${res.statusCode}`);
res.on('data', d => {
process.stdout.write(d);
});
});
req.on('error', error => {
console.error(error);
});
req.end();
}
According with MDN Web Docs:
The async function declaration defines an asynchronous function, which
returns an AsyncFunction object. An asynchronous function is a
function which operates asynchronously via the event loop, using an
implicit Promise to return its result. But the syntax and structure of
your code using async functions is much more like using standard
synchronous functions.
So, You need to return a Promise object in order to be handled by your async function (You could also use another promise to handle it), I converted setBattery to a normal function and the return of this function is now a promise that will be handled by your handler (exports.handler). I haven't tested the code but it should work.
exports.handler = async function (event, context) {
await setBattery();
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
function setBattery() {
'use strict';
const https = require('https');
const options = {
hostname: 'testsite.com',
port: 443,
path: '/proxy/api/setting?EM_OperatingMode=1',
method: 'GET',
headers: {
'Content-Type': 'application/json',
}
};
// Return it as a Promise
return new Promise((resolve, reject) => {
const req = https.request(options, res => {
console.log(`statusCode: ${res.statusCode}`);
res.on('data', d => {
process.stdout.write(d);
// If successful
resolve(d);
});
});
req.on('error', error => {
console.error(error);
// If failed
reject(error);
});
req.end();
});
}
I'm having some problems getting a response from a chained Promise.
I have my component where the chain starts
component
componentDidMount = async ()=> {
try{
const products = await post('payments/getProducts', {});
console.log(products);
} catch(e) {
console.log(e)
}
}
This component calls my API helper:
async function post(url, data) {
token = null;
if (firebase.auth().currentUser) {
token = await firebase.auth().currentUser.getIdToken();
}
try {
const response = axios({
method: 'POST',
headers: {
Authorization: `${token}`,
},
data,
url: `${API_URL}${url}`,
})
return response;
} catch(e){
Promise.reject(e);
}
}
and my API Helper then calls a Firebase Cloud Function which calls Stripe:
paymentRouter.post('/getProducts', (req, res) => {
return stripe.products.list()
.then(products => {
console.log(products.data)
return products.data;
})
.catch(e => {
throw new functions.https.HttpsError('unknown', err.message, e);
})
})
Calling the function is no problem, and my Cloud Function logs out the product data, but I can't get the response to log in my API Helper nor my component.
Promise.reject(e);
That is completely senseless as it creates a new rejected promise that is not used anywhere. You could await it so that it gets chained into the promise returned by the async function, or you just return the promise from axios:
async function post(url, data) {
let token = null; // always declare variables!
if (firebase.auth().currentUser) {
token = await firebase.auth().currentUser.getIdToken();
}
return axios({
method: 'POST',
headers: {
Authorization: `${token}`,
},
data,
url: `${API_URL}${url}`,
});
}
Now the errors don't go into nowhere anymore and you can probably debug the problem :)
Right now I'm learning promises and want to get a token from a webserver, which also uses a promise. I tried it before without a promise but it's also not working.
This is the first block.
promise = new Promise(resolve => {
let accessToken = helper.getAccessToken(baseUrl);
let userCollection = helper.createCollection("user", db);
let excersizeCollection = helper.createCollection("excercise", db);
resolve({
accessToken: accessToken,
database: {
userCollection: userCollection,
excersizeCollection: excersizeCollection
}
});
});
promise
.then(promises => {
console.log("my token" + promises.accessToken);
new nceDefaultbotCommands(bot, promises.accessToken, baseUrl);
new botComamnds(bot, promises.database);
let userController = new reqUserController(
baseUrl,
0,
promises.accessToken
);
bot.start();
})
.catch(() => {
console.log("error");
});
Only the access token is not working, this is in my helper class and it looks like this.
static getAccessToken(baseUrl) {
let promise = new Promise(resolve => {
request.post(
{
url: baseUrl + "/token",
body: {
credentials: {
user: "USER",
password: "PW"
}
},
json: true //// Automatically parses the JSON string in the response
},
(error, response, body) => {
if (error) console.log("error");
if (!error && response.statusCode === 200) {
resolve({ token: body.token });
}
}
);
});
promise.then(resolve => {
console.log(resolve.token);
return resolve.token;
});
}
I get the access token but normally after the then of the first promise.
Thanks in advance.
You're fulfilling your first promise with an object, so that object is the fulfillment value (the promise isn't magically resolved to the promises that are values of properties on that object).
There's no reason to use new Promise when you have a promise or promises to work with, just chain off them; in this case, via Promise.all:
Promise.all([
helper.getAccessToken(baseUrl),
helper.createCollection("user", db),
helper.createCollection("excercise", db)
])
.then(([accessToken, userCollection, exersizeCollection]) => { // Note the destructuring
console.log("my token" + accessToken);
new nceDefaultbotCommands(bot, accessToken, baseUrl);
new botComamnds(bot, {userCollection, exersizeCollection});
let userController = new reqUserController(baseUrl, 0, accessToken);
bot.start();
})
.catch(/*...*/);
Note I corrected the spelling of "exercise," which may require changes to your botCommands constructor.
You do not return your Promise:
static getAccessToken(baseUrl) {
let promise = new Promise(resolve => {
...
});
return promise.then(resolve => {
console.log(resolve.token);
return resolve.token;
});
}
Then I think you need to handle it like Promise, somewhat like:
promise = new Promise(resolve => {
let accessToken = helper.getAccessToken(baseUrl).then(token => {
let userCollection = helper.createCollection("user", db);
let excersizeCollection = helper.createCollection("excercise", db);
resolve({
accessToken: accessToken,
database: {
userCollection: userCollection,
excersizeCollection: excersizeCollection
}
});
});
});