This question already has answers here:
Chained promises not passing on rejection
(4 answers)
Closed 3 years ago.
I want to return a fetch promise to upper layer to use, but I found even this fetch promise fail (be catched), upper layer's then still be called. Is it possible "upper layer's then" only be called when fetch success?
export default function request(url, options) {
.......
return fetch(url, options)
.then(checkStatus)
.then(parseJSON)
.then(data => {
// debugPrint("receive response" + JSON.stringify(data));
if (+data.status.code !== 200) {
message.error(data.status.message || "please retry");
}
return data;
})
.catch(err => {
message.error(err.toString() || "please retry");
return err;
});
}
// then I call request this way:
export function userLogin(account) {
return request(`${domain}/signin/get_accesstoken`, {
method: "POST"
}).then(data => {
// even catch be called, this then still be called. Is it possible only call this then when catch not be called ?
do something;
return data;
});
}
Second edit:
I try to return a promise in then, but look like it is not a promise be returned, I don't know why.
export default function request(url, options) {
.......
return fetch(url, options)
.then(checkStatus)
.then(parseJSON)
.then(data => {
// debugPrint("receive response" + JSON.stringify(data));
if (+data.status.code !== 200) {
message.error(data.status.message || "please retry");
}
return new Promise(resolve=>{
resolve(data)
});
})
.catch(err => {
message.error(err.toString() || "please retry");
return new Promise((resolve, reject)=>{
reject(err)
});
});
}
Edit third:
export default function request(url, options) {
.......
return fetch(url, options)
.then(checkStatus)
.then(parseJSON)
.then(data => {
// debugPrint("receive response" + JSON.stringify(data));
if (+data.status.code !== 200) {
message.error(data.status.message || "please retry");
}
return data;
})
.catch(err => {
message.error(err.toString() || "please retry");
return;
});
}
// then I call request this way:
export function userLogin(account) {
return request(`${domain}/signin/get_accesstoken`, {
method: "POST"
}).then(data => {
// add this
if (!data) {
return
}
do something;
return data;
});
}
if you want to call your upper layer's then only in case of success then throw some error in catch block of fetch instead of returning err.
export default function request(url, options) {
.......
return fetch(url, options)
.then(checkStatus)
.then(parseJSON)
.then(data => {
// debugPrint("receive response" + JSON.stringify(data));
if (+data.status.code !== 200) {
message.error(data.status.message || "please retry");
}
return data;
})
.catch(err => {
message.error(err.toString() || "please retry");
throw new Error('fetch failed'); // throw error
});
}
Related
i was trying out promise code but it always returns me resolve even if the user does not exist in the database
can anyone help me fix my code and the return statement
in the return function the the second console log is only working.
here is my code
Api Call
const email = 't#t.com';
const request = require('request');
function IsUserExists(email, kc_accessToken) {
let url = `${path}/users?email=${email}`;
return new Promise(function (resolve, reject) {
request(
{
url: url,
headers: {
'content-type': 'application/json',
authorization: `Bearer ${kc_accessToken}`,
},
},
function (error, response, body) {
if (error) {
console.log('some error occured');
}
if (response.body.length > 0) {
console.log('User Exist');
return resolve();
}
console.log('Does not Exist');
return reject();
}
);
});
}
Function Call
http
.createServer(function Test() {
getAccessToken()
.then(function (response) {
kc_accessToken = response.data.access_token;
IsUserExists(email, kc_accessToken).then((resp) => {
if (resp) {
console.log('Do Not Create');
} else if (!resp) {
console.log('Creat a new User');
}
});
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
})
.listen(8081);
When Provided user email which exist ( t#t.com )
When Provided user email which does not exist( 09#t.com )
I need to create a new answer for example to you question in comments.
Now, you go into the reject function so you need to handle this rejection in the outside.
if (response.body.length > 0) {
console.log('User Exist');
return resolve();
}
console.log('Does not Exist');
return reject(); // -> Now here you are
You need add .catch function after IsUserExists.then().
It will be IsUserExists.then().catch()
http.createServer(function Test() {
getAccessToken()
.then(function (response) {
kc_accessToken = response.data.access_token;
// here you only accept the data from resolve in Promise
// so you need to add .catch function to handle the rejection.
IsUserExists(email, kc_accessToken).then((resp) => {
if (resp) {
console.log('Do Not Create');
} else if (!resp) {
console.log('Creat a new User');
}
}).catch((error) => {
console.log(error)
});
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
})
.listen(8081);
By the way, you could add parameter in rejection function like reject(new Error("user not found)).
Then in the outside, you can get this rejection message.
The following asynchronous function returns 2 callbacks, so I did what I usually do to return the response
Added return before the fetch
Added return before the result (json.access_token)
but this time console.log(httpResponse, 'fetch json') is undefined on the console and console.log(json.access_token) return the right value.
What do I need to change?
From client
GetJSON(NewURLCode).then(httpResponse => {
console.log(httpResponse, 'fetch json')
}
From Server
GetJSON(NewURLCode){
return fetch("https://accounts.google.com/o/oauth2/token", {
"method": "post",
"headers": {
"Content-Type": 'application/x-www-form-urlencoded'
},
'body': data
}).then((httpResponse) => {
if (httpResponse.ok) {
return httpResponse.json();
} else {
return Promise.reject("Fetch did not succeed");
}
}).then((json) => {
console.log(json.access_token)
return json.access_token
}).catch(err => console.log(err));
}
Unlike the previous function, the following function has only one promise and returns the right object from the client
client
insert_coll ('Token',toInsert).then((ins_result) => {consule.log(ins_result)}
Backend
insert_coll{
return wixData.update(myCollection, toUpdate, options)
.then( ( results) => {
let item = results; //see item below
return results
} )
.catch( (err) => {
let errorMsg = err;
} );
}
}
The error was not accrued because of the return statement, I added a return before httpResponse.json();
It caused because the WIX onReady component called twice...
So for solving this issue I used the following WIX solution :
$w.onReady(function () {
if (wixWindow.rendering.env === "browser") {
//your code
}})
You can return that fetch itself, and handle those stuffs in client.
Like,
Server
GetJSON(NewURLCode){
return fetch("https://accounts.google.com/o/oauth2/token", {
"method": "post",
"headers": {
"Content-Type": 'application/x-www-form-urlencoded'
},
'body': data
});
}
Client
GetJSON(NewURLCode).then(httpResponse => {
if (httpResponse.ok) {
httpResponse.json();
} else {
Promise.reject("Fetch did not succeed");
}
}).then((json) => {
console.log(json.access_token)
return json.access_token
}).catch(err => console.log(err));
}
Otherwise, just return a Promise after those are resolved in the server. Like,
Server
async GetJSON(NewURLCode){
return new Promise(async (resolve, reject) => {
try {
const httpResponse= await fetch("https://accounts.google.com/o/oauth2/token", {
"method": "post",
"headers": {
"Content-Type": 'application/x-www-form-urlencoded'
},
'body': data
});
if (httpResponse.ok) {
const json = await httpResponse.json();
resolve(res.access_token);
} else {
reject("Fetch did not succeed");
}
} catch(err) {
reject(err);
}
});
}
Client
GetJSON(NewURLCode).then(httpResponse => {
console.log(httpResponse, 'fetch json')
}).catch(err => console.log(err));
This question already has answers here:
What's the difference between returning value or Promise.resolve from then()
(6 answers)
Closed 4 years ago.
I have questions about promises. I'm just starting to deal with them and it's not that easy to understand!
I'm trying to setup an authentication system for my app.
RegisterPage
handleSubmit looks like that:
handleSubmit(event) {
event.preventDefault();
const { user } = this.state;
//some code here
userActions.register(user);
}
UserActions
function register(user) {
userService.register(user)
.then(
user => {
success(user);
},
error => {
failure(error.toString());
}
);
function success(user) { return { type: "REGISTER_SUCCESS", user } }
function failure(error) { return { type: "REGISTER_ERROR", error } }
}
UserService
function register(user) {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(user)
};
return fetch(`/api/users/register`, requestOptions).then(handleResponse);
}
function handleResponse(response) {
return response.text().then(text => {
const data = text && JSON.parse(text);
if (!response.ok) {
const error = (data && data.message) || response.statusText;
return Promise.reject(error);
}
return data;
});
}
Question 1. That code is "working" but not like I want. That way, even if the request success, I still can have error from the server, like duplicate username or something like that. I guess what I want is to return Promise.reject() not just if !response.ok but also if I have errors in the JSON returned right?
function handleResponse(response) {
return response.text().then(text => {
const data = text && JSON.parse(text);
if (!response.ok) {
const error = (data && data.message) || response.statusText;
return Promise.reject(error);
}
else if(data.errors) {
return Promise.reject(data.message);
}
return data;
});
}
Question 2. If everything's fine, should I return data or return Promise.resolve(data)? And why?
Checkout the documentation for fetch here: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful
It seems you should be using .catch() to get server errors and just use throw new Error() for having errors.
You don't really need to use Promise.resolve or Promise.reject.
To help refactor what you have, you can try this
function register(user) {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(user)
};
return fetch(`/api/users/register`, requestOptions).then(handleResponse);
}
function handleResponse(response) {
return response.text()
.then(text => {
if (!response.ok) {
const error = (data && data.message) || response.statusText;
throw new Error(error);
} else {
const data = text && JSON.parse(text);
return data;
}
})
.catch(error => throw new Error(err));
}
Hi I'm new so sorry if my question does not formulate properly.
I want to define a promise from axios js in a global function.
Here I want to handle / catch the 401 status globally and logout the user.
I do not want to handle it in every single query.
Here my source global function to handle a request:
export function requestData (url, payload = {}) {
return axios.post(url, payload)
.then(response => {
return response.data
})
.catch(error => {
if (error.response.status === 401) {
logout()
} else {
return error
}
})
}
And here a example function I use on a controller:
requestData('/api/persons', {options: this.options, search: search})
.then(data => {
this.data = data
})
.catch(error => {
this.error = error.toString()
})
My Problem is that the promise catch in my controller will not fire when there is an exception. How to realize this?
change return error in your requestData function to throw error
As per the Axios docs
You can intercept requests or responses before they are handled by then or catch.
You're going to want to use the Response Interceptor:
axios.interceptors.response.use(function(response) {
// Do something with response data
return response;
}, function(error) {
// Do something with response error
if (error.status === 401) {
logout()
}
return Promise.reject(error);
});
Replacing return error by throw error is the half work.
When I'm right the throw error in promise catch will not invoke the next promise .catch statement. This will work in the .then statement.
This way it should work:
export function requestData (url, payload = {}) {
return axios.post(url, payload)
.then(response => {
return response.data
})
.catch(error => {
if (error.response.status === 401) {
logout()
} else {
return error
}
})
.then(result => {
if (result instanceof Error) {
throw result
} else {
return result
}
})
}
I'm trying to convert my existing code using BlueBird, please suggest a best option to chain multiple request. Error happening in each callback needs to be redirected to rendered with different error.
request(option1, function (error, response, body) {
if (!error && response.statusCode == 200) {
var data= JSON.parse(body);
if(data.valid){
if(data.expired){
next();
} else {
request(option2, function (error2, response2, body2) {
var data2= JSON.parse(body2);
if(data2.valid) {
request(option3, function (error3, response3, body3) {
next();
})
} else {
res.json({error:'Error1'});
}
})
}
} else {
res.json({error:'Error2'});
}
} else {
res.json({error:'Error3'});
}
})
This is pretty straightforward, also note your current code doesn't handle errors in the second and third requests and this does:
var request = require("request-promise"); // request - converted to bluebird
request(option1).then(data=> {
if(!data.valid) throw Error("Error3");
if(data.expired) return;
return request(option2).then(JSON.parse);
}).then(data2 => {
if(!data2) return; // didn't need to fetch additional data
if(!data2.valid) throw Error("Error2");
return request(option3);
}).then(() => {
next();
}, e => {
res.json(error: e.message);
// better log this.
});
var rp = require('request-promise');
function handleError(err) {
res.json({
error: err.message
});
}
function parse(data) {
if (data) {
return JSON.parse(data);
}
}
rp(option1)
.then(parse)
.then(function (data) {
if (!data || !data.valid) {
throw Error('Error2');
}
if (data.expired) {
return;
}
return option2;
})
.then(rp)
.then(parse)
.then(function (data2) {
if (!data2 || !data2.valid) {
throw Error('Error1');
}
return option3;
})
.then(rp)
.then(parse)
.then(function () {
next();
})
.catch(handleError);
You don't need to manually check for statusCode but if you need to do so, first you have to add resolveWithFullResponse attribute to your option1 object, which allows you to receive the response object:
function checkStatusCode(response) {
if (response.statusCode !== 200) {
throw Error('Error3');
}
return response.body;
}
// add resolveWithFullResponse attribute to option1
option1.resolveWithFullResponse = true;
rp(option1)
.then(checkStatusCode)
.then(parse)
//...