I have some code that looks like this in Next JS
const resApp = await fetch('/api/club/createsignalapp', {
body: JSON.stringify({
name: event.target.name.value,
}),
headers: {
'Content-Type': 'application/json',
},
method: 'POST',
})
const appResult = await resApp.json()
--createsignalapp
export default async (req, res) => {
var mydata
var createApp = function (data) {
var headers = {
'Content-Type': 'application/json; charset=utf-8',
Authorization: `Basic APIKKEY`,
}
var options = {
host: 'onesignal.com',
port: 443,
path: '/api/v1/apps',
method: 'POST',
headers: headers,
}
var https = require('https')
var myreq = https.request(options, function (myres) {
myres.on('data', function (data) {
mydata = JSON.parse(data)
res.statusCode = 200
res.json({
response: {
boolean: true,
alert: '',
message: '',
},
data: mydata
})
})
})
myreq.on('error', function (e) {
console.log(e)
})
myreq.write(JSON.stringify(data))
myreq.end()
}
var message = {
name: req.body.name
}
createApp(message)
}
This hits the error API resolved without sending a response for /api/club/createsignalapp, this may result in stalled requests.
I'm not sure how to do this correctly as i'm getting confused with the awaits and asyncs and requests everywhere.
Happy to hear suggestions.
Thanks
Related
The following is my code:
async function asynccall() {
//POST request (create order)
var data = JSON.stringify({
merchant_urls: {
terms: "https://www.example.com/terms.html",
checkout: "https://atelierdecosmetique.herokuapp.com/checkout",
confirmation: "https://atelierdecosmetique.herokuapp.com/confirmation",
push: "https://www.example.com/api/push",
},
});
var config = {
method: "post",
url: "https://api.playground.klarna.com/checkout/v3/orders/",
headers: {
"Content-Type": "application/json",
Authorization: "",
},
data: data,
};
var orderid = Postrequest.data.order_id;
//GET Request (read order)
var axios = require("axios");
var data1 = JSON.stringify({
merchant_urls: {
confirmation: "https://www.example.com/confirmation.html" + Postrequest.data.order_id,
},
});
var config1 = {
method: "get",
url: "https://api.playground.klarna.com/checkout/v3/orders/",
headers: {
"Content-Type": "application/json",
Authorization:
},
data: data1,
};
//The calls as variables
var Postrequest = await axios(config);
var Getrequest = await axios(config1);
console.log(Getrequest.data.merchant_urls.confirmation)
app.get("/checkout", function(req, res) {
res.render("checkout.ejs", {
datapost: Postrequest.data.html_snippet
})
});
app.get("/confirmation", function(req, res) {
res.render("confirmation.ejs", {
dataget: Getrequest.data.html_snippet
});
});
}
asynccall();
My problem with this code is that the Postrequest.data.order_id is not shown in the GET request's merchant_urls.confirmation URL when I console log it at the end of the code. It should return the confirmation page URL with the order_id response from the POST request at the end. How could I solve this? I know it has to do with asynchronous and synchronous code? I'm stuck and really need this to work.
You need to get the results of the first request before using the returned data in the second.
async function asynccall() {
var axios = require("axios");
//POST request (create order)
var data = JSON.stringify({
merchant_urls: {
terms: "https://www.example.com/terms.html",
checkout: "https://atelierdecosmetique.herokuapp.com/checkout",
confirmation: "https://atelierdecosmetique.herokuapp.com/confirmation",
push: "https://www.example.com/api/push",
},
});
var config = {
method: "post",
url: "https://api.playground.klarna.com/checkout/v3/orders/",
headers: {
"Content-Type": "application/json",
Authorization: "",
},
data: data,
};
var Postrequest = await axios(config);
var orderid = Postrequest.data.order_id;
//GET Request (read order)
var data1 = JSON.stringify({
merchant_urls: {
confirmation: "https://www.example.com/confirmation.html" + Postrequest.data.order_id,
},
});
var config1 = {
method: "get",
url: "https://api.playground.klarna.com/checkout/v3/orders/",
headers: {
"Content-Type": "application/json",
Authorization: ""
},
data: data1,
};
//The calls as variables
var Getrequest = await axios(config1);
console.log(Getrequest.data.merchant_urls.confirmation)
app.get("/checkout", function(req, res) {
res.render("checkout.ejs", {
datapost: Postrequest.data.html_snippet
})
});
app.get("/confirmation", function(req, res) {
res.render("confirmation.ejs", {
dataget: Getrequest.data.html_snippet
});
});
}
asynccall();
I have several API Get request at once in nodejs. Each API have new data every couple minutes.
var express = require('express');
var router = express.Router();
var request = require("request");
let value1, value2, bodyData1, bodyData2;
var options = { method: 'GET',
url: 'https://api.example.com/data1',
qs:
{
valueType: 'MAXIMUM'
},
headers:
{
authorization: 'ABC123456',
accept: 'application/json; charset=utf-8' } };
request(options, function (error, response, body) {
if (error) throw new Error(error);
bodyData1 = JSON.parse(body);
value1 = bodyData1.value;
});
var options = { method: 'GET',
url: 'https://api.example.com/data2',
qs:
{
valueType: 'MAXIMUM'
},
headers:
{
authorization: 'ABC123456',
accept: 'application/json; charset=utf-8' } };
request(options, function (error, response, body) {
if (error) throw new Error(error);
bodyData2 = JSON.parse(body);
value2 = bodyData2.value;
});
router.get('/', function(req, res, next) {
res.render('home', {valueA : value1, valueB: value2});
});
module.exports = router;
I want to know if it is possible to combine them into one function?
Any other things I should concern?
It is possible if you have promises which is currently not the case. You have to wrap your request() call in a Promise. You can do it manually with a custom function requestToPromise.
You can then use Promise.all to call multiple promises in parallel.
function requestToPromise(options) {
return new Promise((resolve, reject) => {
request(options, (error, response, body) => {
if (error) return reject(error);
resolve(body);
});
});
}
var optionsRequest1 = {
method: "GET",
url: "https://api.example.com/data1",
qs: {
valueType: "MAXIMUM"
},
headers: {
authorization: "ABC123456",
accept: "application/json; charset=utf-8"
}
};
var optionsRequest2 = {
method: "GET",
url: "https://api.example.com/data2",
qs: {
valueType: "MAXIMUM"
},
headers: {
authorization: "ABC123456",
accept: "application/json; charset=utf-8"
}
};
var requestPromise1 = requestToPromise(optionsRequest1);
var requestPromise2 = requestToPromise(optionsRequest2);
Promise.all([requestPromise1, requestPromise2]).then(results => {
var [resultPromise1, resultPromise2] = results;
}).catch(error => {
//handle error
});
Instead of using the custom function requestToPromise you can also use util.promisify
const util = require('util');
const requestAsync = util.promisify(request);
Promise.all([requestAsync(optionsRequest1), requestAsync(optionsRequest2)]).then(results => {
var [resultPromise1, resultPromise2] = results;
}).catch(error => {
//handle error
});
You can use Redis cache to store data in memory for fast retrieval and fetch from memory very quickly.
Also, after some interval, you can add them to a database through bulk creation. It will decrease your database call.
// Example in sequilize
await db.table_name.bulkcreate([ {0bj1}, {obj2}..,{obj3 } ]);
I want to retrieve the JSON response from the api call I am doing. Example, I want to retrieve something like this:
{"error":{},"success":true,"data":{"user":"tom","password":"123","skill":"beginner","year":2019,"month":"Mar","day":31,"playmorning":0,"playafternoon":1,"playevening":1}}
This is my API call using fetch in react. (yes I know sending password in URL is bad, it's for a school project)
fetch('/api/user/'+ user + '?password=' + password, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}}).then((res) => {
console.log(res); //I want to get the JSON stuff here
})
This is the API call I am calling.
app.get('/api/user/:user', function (req, res) {
// console.log(JSON.stringify(req));
// var user = req.body.user;
// var password = req.body.password;
var user = req.params.user;
var password = req.query.password;
console.log(user, password);
var result = { error: {} , success:false};
if(user==""){
result["error"]["user"]="user not supplied";
}
if(password==""){
result["error"]["password"]="password not supplied";
}
if(isEmptyObject(result["error"])){
let sql = 'SELECT * FROM user WHERE user=? and password=?;';
db.get(sql, [user, password], function (err, row){
if (err) {
res.status(500);
result["error"]["db"] = err.message;
} else if (row) {
res.status(200);
result.data = row;
result.success = true;
} else {
res.status(401);
result.success = false;
result["error"]["login"] = "login failed";
}
res.json(result);
});
} else {
res.status(400);
res.json(result);
}
});
When I do console.log(res) in the fetch call, this is what is printed:
Response {type: "basic", url: "http://localhost:3000/api/user/tim?password=123", redirected: false, status: 200, ok: true, …}body: (...)bodyUsed: falseheaders: Headers {}ok: trueredirected: falsestatus: 200statusText: "OK"type: "basic"url: "http://localhost:3000/api/user/tim?password=123"proto: Response
When I visit the website, the output is:
{"error":{},"success":true,"data":{"user":"tom","password":"123","skill":"beginner","year":2019,"month":"Mar","day":31,"playmorning":0,"playafternoon":1,"playevening":1}}
This is what I want.
In general, this is how you return the response body from the Promise.
fetch(`${baseUrl}/api/user/${user}?password=${password}`, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}})
.then(response => response.json())
.then(data=> {
console.log(data);
})
Try this way to parse the response:
fetch('/api/user/'+ user + '?password=' + password, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}}).then(async (res) => {
const raw = await res.text();
const parsed = raw ? JSON.parse(raw) : { success: res.ok };
console.log(parsed);
})
In this case you can also add some checks for response statuses (if you want, of course) along with parsing the result JSON.
for you to get the JSON body content from the response, you need to use json()
fetch('/api/user/'+ user + '?password=' + password, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}}).then((res) => {
const jsonData = res.json();
console.log(jsonData);
})
try this
fetch(${baseUrl}/api/user/${user}?password=${password},{
method:'GET',
headers: {
'Accept': 'application/json',
'Content-Type':
'application/json',
}}) .then(async(response ) => {
await response.json()
})
This is a simple Post request using Axios inside Vue:
import axios from 'axios'
export default {
name: 'HelloWorld',
props: {
msg: String
},
mounted () {
const code = 'test'
const url = 'http://localhost:3456/'
axios.post(url, code, { headers: {'Content-type': 'application/x-www-form-urlencoded', } }).then(this.successHandler).catch(this.errorHandler)
},
methods: {
successHandler (res) {
console.log(res.data)
},
errorHandler (error) {
console.log(error)
}
}
}
The Get method works fine. But Post stay as "Pending" on Network tab. I can confirm that there is a Post method on my webservice and it return something (tested on Postman).
UPDATE
Sending code as a param:
axios(url, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
params: {
code : 'test'
},
}).then(this.successHandler).catch(this.errorHandler)
WEBSERVICE
server.post('/', (req, res, next) => {
const { code } = req.params
const options = {
validate: 'soft',
cheerio: {},
juice: {},
beautify: {},
elements: []
}
heml(code, options).then(
({ html, metadata, errors }) => {
res.send({metadata, html, errors})
next()
})
})
I think there's issue with your axios request structure.
Try this:
const URL = *YOUR_URL*;
axios(URL, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
data: *YOUR_PAYLOAD*,
})
.then(response => response.data)
.catch(error => {
throw error;
});
If you're sending a query param:
axios(URL, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
params: {
code: 'your_string'
},
})
if it is path variable you can set your url:
const url = `http://localhost:3456/${code}`
Let me know if the issue still persists
I also was facing the same. Network call was pending all the time and Mitigated it by passing the response back from server.js(route file) e.g(res.json(1);) and it resolved the issue
I write a test which firstly has to do post request. I get an error when I run this :
the url is :
http://walla.com:8080/internal/getToken
the code :
function user(){
var postData = {
loginName: 'hello#gmail.com',
password: 'abcdef'
}
var options = {
host: 'http://walla.com',
port: '8080',
path: '/internal/getToken',
body: postData
method: 'POST',
headers: {'Content-Type': 'application/json'}
};
var callback = function(response) {
var str = ''
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(str);
});
}
var req = http.request(options, callback);
req.end();
}
describe("ccc", function () {
it("bbbb" , function(){
user();
});
});
Am i doing something wrong?
thanks?
You are missing a comma after the body
var options = {
host: 'http://walla.com',
port: '8080',
path: '/internal/getToken',
body: postData, // Note the Comma at the end
method: 'POST',
headers: {'Content-Type': 'application/json'}
};
Instead, you can directly define the object, like this
var options = {
host: 'http://walla.com',
port: '8080',
path: '/internal/getToken',
body: {
loginName: 'hello#gmail.com',
password: 'abcdef'
},
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};