I have this function using fetch
export async function login(email, password) {
let url = new URL("http://localhost:8080");
url.search = new URLSearchParams({
t: "login",
email: email,
password: password
});
fetch(url, {
method: "GET",
headers: new Headers()
})
.then(response => response.text())
.then(response => {
console.log(response);
return response;
})
.catch(err => console.log(err));
}
And the function that's supposed to call it and handle the result is this
handleSubmit() {
login(this.state.email, this.state.password).then(r => {
console.log(r);
if (String(r) === "true") this.props.updatePath("/main");
else this.setState({ current: 1 });
});
}
I'm new to javascript, and I'm still a bit confused with async thing.
In the console, the log from the second comes before the log from the first function, so I'm assuming it's not waiting for it to function.
The log on the first function spits out the correct result, I just can't get it to the other side.
I was using axios at first (had some problems it with) and this approch worked. Is there something different about fetch that stops this from working?
Any help would be appreciated
The Promise that comes from calling an async function resolves when that function returns. login internally doesn't await anything (that's probably a mistake). It returns before the internal fetch resolves. So while that fetch is in flight, your then callback in handleSubmit runs. Later the fetch initiated in login finishes and logs the actual response.
I would have you try writing login like this:
export async function login(email, password) {
let url = new URL("http://localhost:8080");
url.search = new URLSearchParams({
t: "login",
email: email,
password: password
});
try {
let response = await fetch(url, {
method: "GET",
headers: new Headers()
});
response = await response.text();
console.log(response);
return response;
} catch (err) {
console.log(err);
// original code had this issue where it doesn't reject on error nor resolve to anything useful
}
}
await is very simple concept - it just makes your function wait for the Promise in synchronous manner. In order to make use of it, put await before any expression that returns a Promise. In your case, you can return fetch() in your login() function and then just:
await login(this.state.email, this.state.password);
// execution continued when fetch is done
Related
I'm try to get the return value from my route in golang api,, that return an id.
my route :
POST: http://localhost:1323/profile/valid
my axios request:
export async function validLogin(email, password) {
const data = JSON.stringify({ email, password });
let headers = {
'Content-Type': 'application/json;charset=UTF-8',
};
await axios.post('http://localhost:1323/profile/valid', data, headers)
.then(response => {
return response.data;
})
.catch(err =>{
console.log(err);
});
}
the function works, but return [promise object] or undefined.
The async function always returns Promise. To extract the data out of this function, call await for the promise returned above from another async function.
I'm trying to implement the Stripe payment API in my website. However, I'm not very familiar with JavaScript, which is leading to some issues.
Most of my code is taken from Stripe's website, with some modifications made to better suit my own site.
I have a function CreateCustomer, which is intended to create a customer based on input from a form:
async function createCustomer () {
var emailJSON = {
"email": `${document.querySelector('#email-field').value}`
};
const output = await fetch('/create-customer', {
method: 'post',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(emailJSON)
})
.then((response) => {
return response.json();
})
.then((result) => {
return result;
});
return output;
}
This function is called by another function, and the output is stored because I have another function which requires the customer's Id.
var handleForm = function () {
// other code
const customerPromise = createCustomer();
var customer = customerPromise.data;
// more code
}
The fetch call in CreateCustomer calls the following C# code:
[Route ("create-customer")]
[ApiController]
public class CustomerCreationController : Controller
{
[HttpPost]
public ActionResult Create(CustomerCreateRequest request)
{
var customers = new CustomerService();
var customer = customers.Create(new CustomerCreateOptions
{
Email = request.Email,
});
return Json(new { _customer = customer.Id });
}
public class CustomerCreateRequest
{
[JsonProperty("email")]
public string? Email { get; set; }
}
}
From what I understand about Promises, if I call on the promise before it's resolved, I will get "undefined". But I also think I understand that if I await the promise (as I have done with the fetch in CreateCustomer), this shouldn't be an issue. However, whenever I run this code, I end up saving undefined in my customer variable in handleForm.
Like I said, I'm pretty unfamiliar with JavaScript, so the problem is probably some quirk of the language and/or Promises that I've overlooked. Thanks in advance for your help.
If your createCustomer is async, you need to await it, when calling it:
var handleForm = async function () {
// other code
const customerPromise = await createCustomer();
var customer = customerPromise.data;
// more code
}
#Marco is correct.
You also doing await and including .then witch is redundant.
Here are your options for promises:
// Using async/await
async function createCustomer () {
try {
const requestBody = {
email: `${document.querySelector('#email-field').value}`
};
const response = await fetch('/create-customer', {
method: 'post',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestBody)
})
const data = await response.json()
return data;
} catch (error) {
console.error(error);
}
}
/*
If you are calling createCustomer somewhere it has to
either be a async function to allow await, or
use .then((data) => console.log(data))
*/
const data = await createCustomer();
// Promise chains
async function createCustomer (callback) {
const requestBody = {
email: `${document.querySelector('#email-field').value}`
};
fetch('/create-customer', {
method: 'post',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestBody)
})
.then(response => response.json())
.then(data => callback(data))
.catch(e => console.error(e))
}
createCustomer((data) => {
// do something with data
})
One little thing with fetch is that you also have to await the .json() call. Since that is also a promise.
If you are doing a lot of network requests maybe take a look at axios.
I have never used fetch before, and have followed the documentation, however, no results are being returned from my backend. When I submit the form, the url changes, and all appears fine in my console, but no response from my express backend.
The following code is what I have after my form in a script tag. Can someone please advise?
async function getSample(url = `http://localhost:3000/lookup/${url}`, data = {}) {
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return response.json();
}
document.getElementById('search').addEventListener('submit', function(e) {
event.respondWith(
new Response(myBody, {
headers: {'Content-Type': 'application/json'}
})
);
});
You could try creating a promise and then handling the value returned by the fetch with resolve and reject
async function getSample(url = `http://localhost:3000/lookup/${url}`, data = {}){
return new Promise(function (resolve, reject) {
fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}).then(async response => {
if (response.ok) {
response.json().then(json => resolve(json));
} else {
response.json().then(json => reject(json));
};
}).catch(async error => {
reject(error);
});
});
};
You would then call it like
getSample(...)
.then(results => {
//Code when fetch is successful
}.catch(error => {
//Code when fetch fails
};
I think the problem with it returning nothing is that getSample is an async function, but I imagine you're calling it within a program that isn't async, and so whatever code comes after getSample is using trying to use the value returned from getSample, but nothing's been returned yet, so it's using an empty value. Either that or the return of getSample is happening before the fetch completes. I'm not sure of the exact order that things happen, but a promise should fix your problem
I'm trying to work with async await and fetching data using the fetch api
My problem is, I just don't quite understand how I really get the answer from the server and not the status of the promise. I get the following in the console
Promise {<pending>}
-------------------------------
{locale: "en"}
but what I rather expect is the server response which should be "locale: en".
my code:
const locale = getLocale();
console.log(locale) // here I want to have "locale: en" as a output
async function fetchLocale() {
return await fetch('/get-language', {
headers: {
'Accept': 'application/json'
},
method: 'GET',
}).then(response => {
if (response.ok) {
return response.json()
}
return Promise.reject(Error('error'))
}).catch(error => {
return Promise.reject(Error(error.message))
})
}
async function getLocale() {
return await fetchLocale();
}
The goal I want to archive is, to return this "locale: en" response and store it in the "locale" const at the beginning of my code example.
KR
Your function should look more like this:
async function getLocale() {
let response = await fetch('/get-language', {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'GET',
});
// you can check for response.ok here, and literally just throw an error if you want
return await response.json();
}
And you can consume the result of that in an async function using await
const locale = await getLocale();
console.log(locale);
or by using the promise methods
getLocale().then(function(locale){
console.log(locale);
})
To get the value a Promise resolves with and not the promise itself, use .then() or await. Note that both require a callback or asynchronous context as it's simply not possible to bring this asynchronous result to a synchronous context such as the top level of your file.
getLocale().then(locale => {
console.log(locale);
//locale is only valid here
});
I'm trying to get JSON object from axios
'use strict'
async function getData() {
try {
var ip = location.host;
await axios({
url: http() + ip + '/getData',
method: 'POST',
timeout: 8000,
headers: {
'Content-Type': 'application/json',
}
}).then(function (res) {
console.dir(res); // we are good here, the res has the JSON data
return res;
}).catch(function (err) {
console.error(err);
})
}
catch (err) {
console.error(err);
}
}
Now I need to fetch the res
let dataObj;
getData().then(function (result) {
console.dir(result); // Ooops, the result is undefined
dataObj = result;
});
The code is blocking and waits for the result, but I'm getting undefined instead of object
This seems to be one of those cases where async/await doesn't buy you much. You still need to return a result from the async function, which will return a promise to the caller. You can do that with something like:
async function getData() {
try {
let res = await axios({
url: 'https://jsonplaceholder.typicode.com/posts/1',
method: 'get',
timeout: 8000,
headers: {
'Content-Type': 'application/json',
}
})
if(res.status == 200){
// test for status you want, etc
console.log(res.status)
}
// Don't forget to return something
return res.data
}
catch (err) {
console.error(err);
}
}
getData()
.then(res => console.log(res))
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script>
But in this example, since you don't need to do much in the actual function with the result, you're probably better off just returning axios's promise:
function getDataPromise() {
return axios({
url: 'https://jsonplaceholder.typicode.com/posts/1',
method: 'get',
timeout: 8000,
headers: {
'Content-Type': 'application/json',
}
})
.then(res => res.data)
.catch (err => console.error(err))
}
getDataPromise()
.then(res => console.log(res))
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.js"></script>
It is not what you would like to hear but
Async/Wait works on the principle "Whatever Happens in Vegas - Stays in Vegas". It means you could not pass benefits of using blocking IO calls outside of async block.
If you want to use async/await to create some kind of blocking IO call it would not work unless a block caller is also inside an async function what is not normally the case.
async/wait is only good if you want to have a long chain of IO calls but entire chain still MUST be non-blocking. Individual calls inside chain might be blocking but full chain not.
Example
async fn(url) { //this is a non blocking function
let res = await axios.get("http://jsonservice1"); //blocking but only inside this function
let res2 = await axios.get(url+'?s='+res.data);//res.data is resolved already
return res2; //this how it returns results but it will not be resolved until .then is called what is effectively a callback
}
fn("google.com").then(R=>console.log('sorry I am not blocking '+R.data));
Coming from ajax, I prefer modular approach. Data to be sent, function on success and function on fail are separate from function using axios. Bellow sample code fetch user email against user name form node.js and mysql at the backend.
HTML: <button onclick=" testaxios();">TestAxios</button>
JS in browser:
var data = {
username: "myusername"
}
async function testaxios() {
try {
let res = await axios({
method: 'POST',
data: data,
url: '/testmysql',
});
if (res.status == 200) {
success(res);
};
}
catch (error) {
fail(error);
};
}
function success(res) {
console.log(res.data[0][0].email);
}
function fail(error) {
console.log(error);
}
JS in nodeJS at backend:
app.post("/testmysql", async function (req, res) {
try {
let usrname = req.body.username;
let em = await pool.query("SELECT email FROM users WHERE username = ?", usrname);
res.send(em);
} catch (err) {
console.log(err);
} });