'fetch' from router - how to have 'res.status(400).json('Enter failure message here')' be handled as an error in .then .catch? - json

I have the following code as part of a Button in one of my React Native components. Observe how there is no .catch to handle a possible 'no results' case from server; it is handled with if-statements instead (e.g.: else if (acceptMatchRequestData['status']==='failure') which I was what I'm trying to get away from.
await acceptMatchRequest(match['matchId'], userId, getUserInfoData[0]['ratings'][matchType])
.then(acceptMatchRequestData => {
if (acceptMatchRequestData['status']==='success') {
setMatchInvites(prevState => {
return prevState.filter((observation, i) => observation['matchId'] !== match['matchId'])
})
setMatchScreenParentState('loading')
sendToUserDeviceNotification('matchFound', userId, match['matchedUserId'])
} else if (acceptMatchRequestData['status']==='failure') {
Alert.alert('', acceptMatchRequestData['message'])
}
})
acceptMatchRequest function code:
export async function acceptMatchRequest(matchId, userId, rating) {
console.log('Attempting to accept match request');
info = { matchId, userId, rating }
const firebaseIdToken = await AsyncStorage.getItem('#firebaseIdToken')
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + firebaseIdToken },
body: JSON.stringify(info)
};
const response = await fetch(ngrokOrLocalhost + '/acceptmatchrequest', requestOptions)
const data = await response.json()
return data
}
And server code:
router.post('/acceptmatchrequest', async (req, res) => {
const { matchId, userId, rating } = req.body;
const results = await Match.find({ 'usersInfo.userId': userId, 'matchRecords.matchConfirmed': { $nin: [true] } }).limit(5)
if (results.length===5) {
res.status(400).json({'status': 'failure', 'message': 'You already have 5 active matches. Please finish a match first before you can accept this match.'})
} else {
var filter2 = { '_id': matchId }
var update2 = { 'isCustomRequest_IsAccepted': true, '$push': { 'usersInfo': { 'userId': userId, 'location': { 'type': 'Point', 'coordinates': [0, 0] }, 'rating': rating } } }
var response2 = await Match.findOneAndUpdate(filter2, update2, { new: true, sort: { 'matchCreatedTimestamp': 1 } })
if (response2) {
// Document was updated
res.status(200).json({'status': 'success', 'message': 'Match request was accepted successfully'})
} else {
console.log('Match request was not accepted successfully');
res.status(400).json({'status': 'failure', 'message': 'Match request was not accepted successfully'})
}
}
})

Related

i am trying to get the response from passport.js from node js to react js,i am sending the access and refresh token once user logi's in with google

i am trying to get the response from passport.js from node js to react js,i am sending the access and refresh token once user logi's in with google but i am not sure how to take response from node to react
React Code
const googleAuth = async () => {
window
.open('http://localhost:4000/oauth/google', '_self')
};
Node Code
I can able to verify the user and generate access and refresh token but i am not sure how to get these response in react
passport.use(
new GoogleStrategy(
{
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
callbackURL: "/google/callback",
},
async function (accessToken, res, refreshToken, profile, done) {
done(null, profile);
const enteredemail = profile.emails.map((a) => a.value);
const sftoken = await getSfToken();
var configHeaders = {
method: "get",
headers: {
Authorization: `Bearer ${sftoken}`,
"Content-Type": `application/json`,
},
};
const emailcheck = await axios.get(
`URL`,
configHeaders
);
if (emailcheck.data.success === true) {
const logintoken = await axios.get(
"URL"
);
const acctok = logintoken?.data?.access_token;
const url = `URL`;
const res = await axios.post(
url,
{},
{
headers: {
Authorization: `Bearer ${acctok}`,
},
}
);
const refreshTokenURL = `URL`;
const refresTok = await axios.get(refreshTokenURL, {
headers: {
Authorization: `Bearer ${acctok}`,
},
});
console.log("refreshToken", refresTok);
} else {
return null
}
}
)
);
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});

Web3js BatchRequest Balances from List of Tokens Fails on execute()

This is my batch.js file which contains the relevant code. I am importing some variables from other files but I've isolated the problem to this file:
const Web3 = require('web3')
const fs = require('fs')
const { convertToNumber, getTokens } = require('./utils')
const { abi, bathEndpoint, walletAddress, blockNumber } = require('./constant.js')
const web3 = new Web3(new Web3.providers.HttpProvider(bathEndpoint))
const generateContractFunctionList = ({ tokens, blockNumber }) => {
const batch = new web3.BatchRequest()
tokens.map(async ({ address: tokenAddress, symbol, decimals }) => {
// console.log('tokenAddress :>> ', tokenAddress)
if (tokenAddress != null && tokenAddress != '') {
const contract = new web3.eth.Contract(abi)
contract.options.address = tokenAddress
try {
batch.add(
contract.methods
.balanceOf(walletAddress)
.call.request({}, blockNumber)
)
} catch (error) {
console.error('Error adding request to batch for token ', tokenAddress)
}
}
})
return batch
}
const main = async () => {
//const { tokens } = await getTokens()
const tokens = JSON.parse(fs.readFileSync('./tokenArrayFormatted1.json'));
console.log('tokens retrieved :>> ', tokens.length)
// const batch = generateContractFunctionList({ tokens })
// query block number
const batch = generateContractFunctionList({ tokens, blockNumber: blockNumber })
const tokenBalances = {}
const tokensIgnored = []
let batchData
try {
batchData = await batch.execute()
} catch (error) {
console.error('Error retrieving balances for some tokens')
batchData = error
}
try {
batchData.response.forEach((res, index) => {
const { name, decimals, symbol } = tokens[index]
if (res && res._hex) {
tokenBalances[name] = `${convertToNumber(res._hex, decimals)} ${symbol}`
} else {
tokensIgnored.push(name)
}
})
} catch (error) {
console.error('Error retrieving balances for some tokens')
batchData = error
}
console.log(
'The following tokens returned an error when checking balance:',
tokensIgnored
)
console.log('----------')
console.log(
`Balance checked for ${Object.keys(tokenBalances).length} tokens:`
)
console.log(tokenBalances)
}
main()
tokenArrayFormatted1.json looks like this:
[
{
"chainId": 1,
"address": "0xf3AE5d769e153Ef72b4e3591aC004E89F48107a1",
"name": "Deeper Network",
"symbol": "DPR",
"decimals": 18
},
{
"chainId": 1,
"address": "0xf680429328caaaCabee69b7A9FdB21a71419c063",
"name": "Butterfly Protocol Governance Token",
"symbol": "BFLY",
"decimals": 18
}
]
When I run node batch.js I keep getting an error telling me that batchData.response is undefined when the code tries to do a forEach over it. I logged batch to the console and it looked like this.
Batch {
requestManager: RequestManager {
provider: HttpProvider {
withCredentials: false,
timeout: 0,
headers: undefined,
agent: undefined,
connected: false,
host: 'https://USERNAME:PASSWORD#BASEURLOFGETHNODE.com',
httpsAgent: [Agent]
},
providers: {
WebsocketProvider: [Function: WebsocketProvider],
HttpProvider: [Function: HttpProvider],
IpcProvider: [Function: IpcProvider]
},
subscriptions: Map(0) {}
},
requests: [
{
params: [Array],
callback: undefined,
method: 'eth_call',
format: [Function: bound ]
},
{
params: [Array],
callback: undefined,
method: 'eth_call',
format: [Function: bound ]
}
]
}
Where USERNAME,PASSWORD, and BASEURLOFGETHNODE refer to my actual credentials.
And then batchData which is created by the line let batchData = await batch.execute() is undefined when logged to the console. So clearly await batch.execute() is producing nothing. I am using Chainstack Geth node API's (with an archive node) and web3js as indicated above. What seems to be the problem?
let batchData = await batch.execute()
batch.execute() does not return a promise if you read the source code, in fact it sends the JSON RPC batch request and call each request callback individually, so what you need to do is turn the execute function into asynchronous one returning an array of responses, and this is how to do it :
const Jsonrpc = require('web3-core-requestmanager/src/jsonrpc');
var { errors } = require('web3-core-helpers');
function executeAsync(batch) {
return new Promise((resolve, reject) => {
var requests = batch.requests;
batch.requestManager.sendBatch(requests, (err, results) => {
results = results || [];
var response = requests.map((request, index) => {
return results[index] || {};
}).map((result, index) => {
if (result && result.error) {
return errors.ErrorResponse(result);
}
if (!Jsonrpc.isValidResponse(result)) {
return errors.InvalidResponse(result);
}
return requests[index].format ? requests[index].format(result.result) : result.result;
});
resolve(response);
});
})
}
To use this function :
(async () => {
var batch = new web3.BatchRequest();
batch.add(web3.eth.getBlock.request("latest"));
var batchResponse = await executeAsync(batch);
console.log(batchResponse);
})()

node js stops working on multiple api request from angular and working after restarting the node app

i am developing an app with node express js and angular js. My angular app makes an api request from node js app server on each route or button click, also a single component or button click may request multiple api to node js app. upon requesting multiple time the data loading is just got stopped and i am not getting result. Also getting status code like 304 and 204.
please check out my api code and subscribe service code.
constroller.js ///express js
getList: async (req, res) => {
try{
const result = await getList(); //from service.js (an sql query)
var serviceCalls = result[0][0];
return res.set({'Content-Type': 'application/json'}).status(200).json({
success: 1,
message: 'Successfully Data Fetched',
data: serviceCalls
});
} catch(e){
return res.json({
success: 0,
message: 'No Data Fetched' + ' ' + e.message,
data: {}
});
}
},
getDetails: async (req, res) => {
try{
const id = req.query.id
const result = await getDetails(id); //from service.js (an sql query)
var serviceCalls = result[0][0];
return res.set({'Content-Type': 'application/json'}).status(200).json({
success: 1,
message: 'Successfully Data Fetched',
data: serviceCalls
});
} catch(e){
return res.json({
success: 0,
message: {text:'No Data Fetched ', errMsg: e.message},
data: {}
});
}
},
getTroubles: async (req, res) => {
try{
const id = req.query.id
const result = await getTroubles(id); //from service.js (an sql query)
var complaintData = result[0][0];
return res.set({'Content-Type': 'application/json'}).status(200).json({
success: 1,
message: 'Successfully Data Fetched',
data: complaintData
});
} catch(e){
return res.json({
success: 0,
message: 'No Data Fetched',
data: []
});
}
},
getLogs: async (req, res) => {
try{
const id = req.query.id
const result = await getLogs(id); //from service.js (an sql query)
var feedbackData = result[0][0];
return res.set({'Content-Type': 'application/json'}).status(200).json({
success: 1,
message: 'Successfully Data Fetched',
data: logs
});
} catch(e){
return res.json({
success: 0,
message: {text:'No Data Fetched ', errMsg: e.message},
data: []
});
}
},
routes //node js express js
app.js
app.use('/serviceCall', serviceCallRoute);
serviceCallRoute
router.get("/getList", getList);
router.get("/getDetails", getDetails);
router.get("/getTroubles", getTroubles);
router.get("/getLogs", getLogs);
angular subscribe to api
getServiceCalls() {
return this.http.get(url + 'serviceCall/getList',this.httpOptions)
.pipe(
map((res: IServiceCall) => {
return res;
}),
catchError(errorRes => {
return throwError(errorRes);
})
);
}
getServiceCallDetails(id):Observable<IServiceCall> {
const params = new HttpParams().set('id', id);
const headers = new HttpHeaders({ 'Content-Type': 'application/json'})
return this.http.get(url + 'serviceCall/getDetails',{headers:headers,params: params})
.pipe(
map((res: IServiceCall) => {
return res;
}),
catchError(errorRes => {
return throwError(errorRes);
})
);
}
getServiceCallTroubles(id) {
const params = new HttpParams().set('id', id);
const headers = new HttpHeaders({ 'Content-Type': 'application/json'})
return this.http.get<IServiceCallTroubles>(url + 'serviceCall/getTroubles',{headers:headers,params: params})
.pipe(
map((res: IServiceCallTroubles) => {
return res;
}),
catchError(errorRes => {
return throwError(errorRes);
})
);
}
getServiceCallLogs(id):Observable<IServiceCallLogs>{
const params = new HttpParams().set('id', id);
const headers = new HttpHeaders({ 'Content-Type': 'application/json'})
return this.http.get<IServiceCallLogs>(url + 'serviceCall/getLogs',{headers:headers,params: params})
.pipe(
map((res: IServiceCallLogs) => {
return res;
}),
catchError(errorRes => {
return throwError(errorRes);
})
);
}
The express js is working well. It is fault in database connection limit.
the DB connection limit was set as 10. So,after 10 api request with sql query. The db connection gets disconnected.

MobX State Tree generator does not allow modified state in a successful promise?

Via the code following I get this error:
error: Error: [mobx-state-tree] Cannot modify
'AuthenticationStore#<root>', the object is protected and can only be
modified by using an action.
the code (generator) in question:
.model('AuthenticationStore', {
user: types.frozen(),
loading: types.optional(types.boolean, false),
error: types.frozen()
})
.actions(self => ({
submitLogin: flow(function * (email, password) {
self.error = undefined
self.loading = true
self.user = yield fetch('/api/sign_in', {
method: 'post',
mode: 'cors',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
'user' : {
'email': email,
'password': password
}
})
}).then(res => {
return res.json()
}).then(response => {
self.loading = false // the error happens here!
return response.data
}).catch(error => {
console.error('error:', error)
// self.error = error
})
}), ...
The question: is this not permitted in a generator, is there a better way to update this particular state or does it need to be wrapped by a try/catch?
As always thanks is advance for any and all feedback!
The problem is you're calling then on the Promise returned by fetch(), and the function you pass to then is not an action. Note that functions that run within an action (or flow) do not count as the action itself.
Since you're using yield, you don't need to call then or catch on the Promise returned by fetch(). Instead, wrap it in a try/catch:
submitLogin: flow(function* (email, password) {
self.error = undefined;
self.loading = true;
try {
const res = yield fetch('/api/sign_in', {
method: 'post',
mode: 'cors',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
'user' : {
'email': email,
'password': password
}
})
});
const response = yield res.json();
self.loading = false;
self.user = response;
} catch(error) {
console.log('error: ', error);
self.error = error;
}
}

Convert Promise object to JSON in Angular 2

I'm trying to make an HTTP POST and then check the response to see if it fails or succeeds.
The HTTP call looks like this :
doLogin(credentials) {
var header = new Headers();
header.append('Content-Type', 'application/x-www-form-urlencoded');
var body = 'username=' + credentials.username + '&password=' + credentials.password;
return new Promise((resolve, reject) => {
this.http.post(this.url, body, {
headers: header
})
.subscribe(
data => {
resolve(data.json());
},
error => {
resolve(error.json());
}
);
});
}
And the call of this function is the following :
data: Object;
errorMessage: Object;
login($event, username, password) {
this.credentials = {
username: username,
password: password
};
this._loginService.doLogin(this.credentials).then(
result => {
this.data = result;
console.log(this.data);
},
error => {
this.errorMessage = <any>error;
console.log(this.errorMessage);
});
}
On Chrome console, the data is the following :
Object {status: "Login success", token: "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJjcmlzdGkiLCJ1c2VyS…blf1AzZ6KzRWQFNGXCrIeUHRG3Wrk7ZfCou135WmbVa15iYTA"}
How can I access the status in Angular 2? Because if I'm trying to access this.data.status, it's not working.
Should I create a class with the status and token properties?
To answer your question, you can use the response.okboolean that's available in the subscription of the observable from the http.
So based on your code you could pass the data object straight to the promise and inspect data.ok before parsing the data.json.
//...
return new Promise((resolve, reject) => {
this.http.post(this.url, body, {
headers: header
})
.subscribe(resolve,
error => {
reject(error.json());
}
);
});
// then you would have something like this:
this._loginService.doLogin(this.credentials).then(
result => {
if (result.ok) {
this.data = result;
console.log(this.data);
}
},
error => {
this.errorMessage = <any>error;
console.log(this.errorMessage);
})
SUGGESTION
Now, I would recommend getting rid of the promise, as I believe you don't really need it. whoever is consuming your service can just subscribe to the observable returned by the http post, like so:
doLogin(credentials) {
let header = new Headers();
header.append('Content-Type', 'application/x-www-form-urlencoded');
var body = 'username='+credentials.username+'&password='+credentials.password;
return this.http.post(this.url, body, { headers: header });
}
Then, when logging in:
login($event, username, password) {
this.credentials = {
username: username,
password: password
};
this._loginService.doLogin(this.credentials).subscribe(response => {
if (response.ok) { // <== CHECK Response status
this.data = response.json();
console.log(this.data);
} else {
// handle bad request
}
},
error => {
this.errorMessage = <any>error;
console.log(this.errorMessage);
});
}
Hope this helps!
You could do it like this:
data: Object;
errorMessage: Object;
login($event, username, password) {
this.credentials = {
username: username,
password: password
};
this._loginService.doLogin(this.credentials).then(
(result: any) => {
this.data = result;
console.log(this.data);
console.log(this.data.status);
},
error => {
this.errorMessage = <any>error;
console.log(this.errorMessage);
});
}
Set the result to type any. That way you'll be able to access the status, however you could create a class and use rxjs/map within your service to populate the class if you so desire.