internal, implementation, error,handler method did not return a value, a promise, or throw an error - hapi

Am trying to get data using postman but am getting handler method did not return a value yet i can console.log results. What might be the problem with my code?
{
method: 'GET',
path: '/departments',
handler: (request, h) => {
// let results=[];
connection.query('SELECT * FROM departments', function (Error, results) {
if (Error) {
console.log(Error);
return Error;
}
console.log(JSON.stringify(results));
});
return h.response(results);
}
}

Related

How to use refetch method to send different queries using useQuery in react-query

I'm working with react-query in ReactJS to build a website.
I have the following code, where I fetch some data using useQuery():
const { error, data: movie, status, refetch } = useQuery({
queryKey: 'key1',
queryFn: async () => {
return await Promise.all([
axios.get(`API-1.com/get-some-data`), /*getting some data from api-1 */
axios.get(`API-2.com/get-some-data`), /*getting some data from api-2 */
]).then(([api1, ap2]) => {
return { data1: api1, data2: api2 }
})
}
})
The problem I'm facing is getting somtimes a 404 response from one of the apis, so I need to refetch the data just from the other api that doesn't cause the error.
I tried to use the refetch method inside onError, but it can't be used with parameters.
onError: (error) => {
refetch() /* refetch can't be used with parameters */
},
How can I handle this problem?
I ended up doing the following:
Writing the fetching part in an external function (so I can call the function with parameters)
Adding a try-catch block inside the queryFn to handle the errors
/********* this is the function where I fetch the data. *********/.
/********* with a param that tells me if i'll call API-2 or not *********/
const fetchData = async ({ isDataFoundInApi2 }) => {
return await Promise.all([
axios.get(`API-1.com/get-some-data`),
(!isDataFoundInApi2 && axios.get(`API-2.com/get-some-data`)),
]).then(([api1, api2]) => {
return { data1: api1, data2: api2 }
})
/********* the useQuery where the above method is called *********/
/********* first it sends true as a bool value, then if no *********/
/********* data was found in API-2, it sends false *********/
/********* from `catch` to prevent the fetching from API-2 *********/
const { error, data: movie, status } = useQuery({
queryKey: 'key1',
queryFn: async () => {
try {
return await fetchData({})
} catch (error) {
if (error.response?.status === 404)
return await fetchData({ isDataFoundInApi2: true }) // true means call only the first api
}
},
})

how to get callback return value in nestjs

I am going to use vonage for text service.
However, only node.js syntax exists, and the corresponding API is being used.
There is a phenomenon that the callback is executed later when trying to receive the values ​​returned from the callback to check for an error.
How can I solve this part? The code is below.
await vonage.message.sendSms(from, to, text, async (err, responseData) => {
if (err) {
console.log('1');
result.message = err;
} else {
if (responseData.messages[0]['status'] === '0') {
console.log('2');
} else {
console.log('3');
result.error = `Message failed with error: ${responseData.messages[0]['error-text']}`;
}
}
});
console.log(result);
return result;
When an error occurs as a result of executing the above code,
result{error:undefined}
3
Outputs are in order.
From what I can understand the issue is that you are passing a async callback. you could simply just give vonage.message.sendSms() a synchronous callback like so.
const result = {};
vonage.message.sendSms(from, to, text, (err, responseData) => {
if (err) {
console.log('1');
result.message = err;
} else {
if (responseData.messages[0]['status'] === '0') {
console.log('2');
} else {
console.log('3');
result.error = `Message failed with error: ${responseData.messages[0]['error-text']}`;
}
}
});
if you want to use async or promises I would suggest something like this
const sendSMS = (from, to, text) => new Promise( (resolve, reject) => {
vonage.message.sendSms(from, to, text, (err, responseData) => {
if (err) {
reject(err);
} else {
resolve(responseData);
}
});
});
// elsewhere
sendSMS(from, to, text)
.then(...)
.catch(...);

How to get axios error response INTO the redux saga catch method

With axios the code is:
export const createBlaBla = (payload) => {
return axios.post('/some-url', payload)
.then(response => response)
.catch(err => err);
}
And then I'm using this with redux-saga like this:
function* createBlaBlaFlow(action) {
try {
const response = yield call(createBlaBla, action.payload);
if (response) {
yield put({
type: CREATE_BLA_BLA_SUCCESS
});
}
} catch (err) {
// I need the error data here ..
yield put({
type: CREATE_BLA_BLA_FAILURE,
payload: 'failed to create bla-bla'
});
}
}
In case of some error on the backend - like invalid data send to the backend - it returns a 400 response with some data:
{
"code":"ERR-1000",
"message":"Validation failed because ..."
"method":"POST",
"errorDetails":"..."
}
But I don't receive this useful data in the catch statement inside the saga. I can console.log() the data in the axios catch statement, also I can get it inside the try statement in the saga, but it never arrives in the catch.
Probably I need to do something else? ... Or the server shouldn't return 400 response in this case?
So, I came up with two solutions of this problem.
===
First one - very dump workaround, but actually it can be handy in some specific cases.
In the saga, right before we call the function with the axios call inside, we have a variable for the errors and a callback that sets that variable:
let errorResponseData = {};
const errorCallback = (usefulErrorData) => {
errorResponseData = usefulErrorData;
};
Then - in the axios method we have this:
export const createBlaBla = (payload, errCallback) => {
return axios.post('/some-url', payload)
.then(response => response)
.catch(err => {
if (err && err.response.data && typeof errCallback === 'function') {
errCallback(err.response.data);
}
return err;
});
}
This way, when we make request and the backend returns errors - we'll call the callback and will provide the errors from the backend there. This way - in the saga - we have the errors in a variable and can use it as we want.
===
However, another solution came to me from another forum.
The problem I have is because in the method with the axios call I have catch, which means that the errors won't bubble in the generator. So - if we modify the method with the axios call like this:
export const createBlaBla = (payload) => {
return axios.post('/some-url', payload)
}
Then in the catch statement in the saga we'll have the actual backend error.
Hope this helps someone else :)
In your API call you can do the following:
const someAPICall = (action) => {
return axios.put(`some/path/to/api`, data, {
withCredentials: true,
validateStatus: (status) => {
return (status == 200 || status === 403);
}
});
};
Please note the validateStatus() part - this way when axios will encounter 200 or 403 response, it will not throw Error and you will be able to process the response after
const response = yield call(someAPICall, action);
if (response.status === 200) {
// Proceed further
} else if (response.status === 403) {
// Inform user about error
} else {
...
}

Return data in json after subscribe

I am using Angular 5 and want to return data from function getDionaeaResults in json format after subscribing to service
getDionaeaResults(sql) : any {
this.dionaeaService.getDionaeaConnectionLogs(sql).subscribe(res => {
this.data = res;
}),
(error: any) => {
console.log(error);
});
return this.data;
}
After calling this function, this.totalAttacks prints undefined.
getTotalAttack() {
this.totalAttacks = this.getDionaeaResults("some query")
console.log(this.totalAttacks,'attacks')
}
Would suggest using the Obseravable .map() function.
getDionaeaResults(sql) : Observable<any> {
return this.dionaeaService
.getDionaeaConnectionLogs(sql)
.map(res => res);
}
getTotalAttack(sql){
this.getDionaeaResults("some query")
.subscribe(
res => { this.totalAttacks = res; },
err => { console.log(err); }
);
}
this.getDionaeaResults is returning undefined because the service you're calling is asynchronous you have to wait for the subscribe callback. as Observables are asynchronous calls
this.data=res
might execute after the return statement. You can perhaps call that dionaeaService directly inside getTotalAttack() function, like this:
getTotalAttack(sql){
this.dionaeaService.getDionaeaConnectionLogs(sql).subscribe(res => {
this.totalAttacks = res;
}),
(error: any) => {
console.log(error);
});
}

Multiple functions in restify function to elasticsearch client

I'm building a REST API using node and restify that communicaties with an elasticsearch database. Now when I delete an object, I want this to do a kind of cascading delete to some other objects. I know this is not really what to use elasticsearch for but bear with me.
So here is my code:
function deleteHostname(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
var endpoints = [];
client.search({
index: 'test',
type: 'something',
body: {
from: 0, size: 100,
query: {
match: {
hostname: 'www.test.com'
}
}
}
}).then(function (error, resp) {
if(error) {
res.send(error);
}
endpoints = resp.hits.hits;
for (index = 0, len = endpoints.length; index < len; ++index) {
client.delete({
index: 'test',
type: 'something',
id: endpoints[index]._id
}, function (error, response) {
if(error) {
res.send(error);
}
});
}
res.send(endpoints);
return next();
});
}
So basically I just want to search for any objects with hostname www.test.com ( I just hard coded this to test it ). Then I want to delete all objects I found. It follows the error path and sends me this:
{
"took":1,
"timed_out":false,
"_shards":{
"total":5,
"successful":5,
"failed":0
},
"hits":{
"total":1,
"max_score":2.098612,
"hits":[
{
"_index":"test",
"_type":"something",
"_id":"123456",
"_score":2.098612,
"_source":{
"duration":107182,
"date":"2016-05-04 00:54:43",
"isExceptional":true,
"hostname":"www.test.com",
"eta":613,
"hasWarnings":false,
"grade":"A+",
"ipAddress":"ipip",
"progress":100,
"delegation":2,
"statusMessage":"Ready"
}
}
]
}
}
So in my opinion this doesn't look like an error? So why am I getting it back as an error? If I remove:
if(error) {
res.send(error);
}
From my code, I won't get any response.
You need to change your code like this (see the changes denoted by -> to the left):
if(error) {
1-> return res.send(error);
}
endpoints = resp.hits.hits;
for (index = 0, len = endpoints.length; index < len; ++index) {
2-> (function(id){
client.delete({
index: 'test',
type: 'something',
3-> id: id
}, function (error, response) {
if(error) {
4-> next(error);
}
});
5-> })(endpoints[index._id]);
}
6-> //res.send(endpoints);
I'm now explaining each change:
If you don't return you'll send the error and then you'll continue with processing the hits
(3/5) Since client.delete is an asynchronous function, you need to call it in an anonymous function
In case of error you need to call next(error) not res.send
You cannot send the response at this point since your for loop might not be terminated yet. Instead of a for loop, you should use the excellent async library instead (see an example of using asynch.each below)
Async example:
var async = require('async');
...
if(error) {
return res.send(error);
}
endpoints = resp.hits.hits;
async.each(endpoints,
function(endpoint, callback) {
client.delete({
index: 'test',
type: 'something',
id: endpoint._id
}, callback);
},
// this is called when all deletes are done
function(err){
if (err) {
next(err);
} else {
res.send(endpoints);
next();
}
}
);
Another solution for you to achieve exactly what you want is to use the delete by query plugin. That feature allows you to do all the above in a single query.
If you are still on ES 1.x, delete-by-query is still part of the core and you can simply call the deleteByQuery function of the Javascript client.
If you are on ES 2.x, delete-by-query is now a plugin, so yo need to install it and then also require the deleteByQuery extension library for the Javascript client
function deleteHostname(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
client.deleteByQuery({
index: 'test',
type: 'something',
body: {
query: {
match: { hostname: 'www.test.com' }
}
}
}, function (error, response) {
if (error) {
next(error);
} else {
res.send(endpoints);
next();
}
});
}