use await inside callback (Microsoft Bot Framework v4 nodejs) - javascript

I am trying to send the response back to chatbot emulator from inside callback.
async getUserDetails(step){
console.log("inside get userdetaiuls modeiule")
this.userDBObject.password = step.result;
this.userDBMethod ( async function(response){
console.log("inside callback return");
console.log(response);
await step.context.sendActivity(response); // not able to do this step
return step.endDialog();
});
}
async userDBMethod(callback){
request.post('#',
{form:{key: 'hi'}}, function (error, response, body) {
callback("done");
});
}
The error which I'm getting is:
(node:17424) UnhandledPromiseRejectionWarning: TypeError: Cannot
perform 'get' on a proxy that has been revoked
at D:\LCI\Usecases\statementBalance\lionsbot-src\bot.js:384:32
at Request._callback (D:\LCI\Usecases\statementBalance\lionsbot-src\bot.js:410:17)
at Request.self.callback (D:\LCI\Usecases\statementBalance\lionsbot-src\node_modules\request\request.js:185:22)
at Request.emit (events.js:182:13)
at Request.EventEmitter.emit (domain.js:442:20)
at Request. (D:\LCI\Usecases\statementBalance\lionsbot-src\node_modules\request\request.js:1161:10)
at Request.emit (events.js:182:13)
at Request.EventEmitter.emit (domain.js:442:20)
at IncomingMessage. (D:\LCI\Usecases\statementBalance\lionsbot-src\node_modules\request\request.js:1083:12)
at Object.onceWrapper (events.js:273:13) (node:17424) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This
error originated either by throwing inside of an async function
without a catch block, or by rejecting a promise which was not handled
with .catch(). (rejection id: 1) (node:17424) [DEP0018]
DeprecationWarning: Unhandled promise rejections are deprecated. In
the future, promise rejections that are not handled will terminate the
Node.js process with a non-zero exit code.
So how can I use await inside callback to send response back to the user.
Thanks !

I would recommend using Axios - a promise based HTTP client for node.js - rather than the request package. Since Axios is promise based, you can use async/await instead of callbacks. The resulting code falls more in line with the flow of the BotFramework. For more details, see the code snippet below and the Axios Documentation.
async getUserDetails(step){
this.userDBObject.password = step.result;
try {
const res = await axios.post('#', {form:{key: 'hi'}});
await step.context.sendActivity("Done");
} catch (error) {
console.log(error);
await step.context.sendActivity("Sorry, we were not able to complete your request.");
}
return step.endDialog();
}

Related

UnhandledPromiseRejectionWarning: ReferenceError: fetch is not defined [duplicate]

This question already has answers here:
ReferenceError: fetch is not defined
(25 answers)
Closed 1 year ago.
I tried using .then response and .catch but nothing worked. I am getting the below error when running test script .
I dont want to use node-fetch method
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
});
const json = await response.json();
Can anyone able to tell me what i am missing here?
(Use node --trace-warnings ... to show where the warning was created)
(node:12784) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (rejection id: 2)
(node:12784) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
fetch is not a javascript but a browser spec. See e.g. here for details on fetch.
The only solution is to use a node package as the mentioned node-fetch or use the default node http lib. From the docs:
var http = require('http');
//The url we want is: 'www.random.org/integers/?num=1&min=1&max=10&col=1&base=10&format=plain&rnd=new'
var options = {
host: 'www.random.org',
path: '/integers/?num=1&min=1&max=10&col=1&base=10&format=plain&rnd=new'
};
callback = function(response) {
var str = '';
//another chunk of data has been received, so append it to `str`
response.on('data', function (chunk) {
str += chunk;
});
//the whole response has been received, so we just print it out here
response.on('end', function () {
console.log(str);
});
}
http.request(options, callback).end();

Cannot set headers after they are sent to the client with postman

I have a problem with my POST. I'm trying to send a request with Postman Postman screen but I have an error in the terminal.
My code:
exports.createSauce = (req, res, next) => {
const sauce = new Sauce({
...req.body
})
sauce.save()
.then(res.status(201).json({ message : "registered object !" }))
.catch(error => res.status(400).json({ error }))
}
My error message :
(node:2808) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:481:11)
at ServerResponse.header (C:\Users\Admin\Desktop\Workspace\P6_saumureau_thibaud\node_modules\express\lib\response.js:771:10)
at ServerResponse.send (C:\Users\Admin\Desktop\Workspace\P6_saumureau_thibaud\node_modules\express\lib\response.js:170:12)
at ServerResponse.json (C:\Users\Admin\Desktop\Workspace\P6_saumureau_thibaud\node_modules\express\lib\response.js:267:15)
at sauce.save.then.catch.error (C:\Users\Admin\Desktop\Workspace\P6_saumureau_thibaud\controllers\sauce.js:9:37)
at process._tickCallback (internal/process/next_tick.js:178:7)
(node:2808) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:2808) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Someone have a solution ?
Thanks in advance :)
The line .then(res.status(201).json({ message : "registered object !" })) calls res.status(201).json({ message : "registered object !" }) imediatly and uses the result of that call as parameter passed to then.
So your res.status(201).json({ message : "registered object !" }) will always be executed no matter if save was successful or not and will be called before the save happened.
According to the error message your save fails, so you first call res.status(201).json({ message : "registered object !" }) which sends header and body to the client, and then you call res.status(400).json({ error }) which trys to send headers again, but the request was already send.
You have to convert the part in the then to a callback using e.g. an arrow function: .then(() => res.status(201).json({ message : "registered object !" }))

Invalid distance too far back zlib nodejs

I'm trying to compress and decompress the contents of a HTML file using zlib, to be able to send it over a post request to my database. I've got this code here, for example.
const { deflate, unzip } = require('zlib');
const input = '.................................';
deflate(input, (err, buffer) => {
if (err) {
console.error('An error occurred:', err);
process.exitCode = 1;
}
console.log(buffer.toString('base64'));
});
const buffer = Buffer.from('eJzT0yMAAGTvBe8=', 'base64');
unzip(buffer, (err, buffer) => {
if (err) {
console.error('An error occurred:', err);
process.exitCode = 1;
}
console.log(buffer.toString());
});
This is from NodeJS's official website, and it seems to work. It can compress and decompress the variable input. When I try to use this with my own variable, containing the HTML, deflating it worked; however, inflating it back into a string throws the error
(node:1353) UnhandledPromiseRejectionWarning: Error: invalid distance too far back
at Zlib.zlibOnError [as onerror] (zlib.js:182:17)
at processChunkSync (zlib.js:431:12)
at zlibBufferSync (zlib.js:168:12)
at Object.syncBufferWrapper [as unzipSync] (zlib.js:766:14)
at inflateString (/home/runner/woc-bot/functions.js:62:36)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:1353) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:1353) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I think this means that the encoded string that my database returns is corrupted, so I tried to just send a simple encoded string to the database, fetch it back, and then inflate it again.
const { deflate} = require('zlib');
const input = 'Hellow worldw';
deflate(input, (err, buffer) => {
if (err) {
console.error('An error occurred:', err);
process.exitCode = 1;
}
console.log(buffer.toString('base64'));
});
I get eJzzSM3JyS9XKM8vykkpBwAjDAUr, so I send this to the database, and get it back. I unzip it, and it returns hellow worldw
I'm really not sure what's happening, I'm using Repl.it's database (plz dont judge me) and this has been killing me for the past two days.

Spotify API Node.js

I was trying to make a get request to the spotify API using axios in node.js. But, I always end up getting a 400 bad request. Could someone please help me out? The code snippet and the error are pasted below.
app.get('/api/search', async (req, res) => {
const spotify_search_one = await axios.get('https://api.spotify.com/v1/search', {
headers: {
'Authorization': keys.spotifyClientId
},
params: {
q: "face",
type: "track"
}
});
console.log(spotify_search_one);
})
The error is as follows
UnhandledPromiseRejectionWarning: Error: Request failed with status code 400
[0] at createError (/Users/uddhavbhagat/Desktop/Projects/TuneIn/node_modules/axios/lib/core/createError.js:16:15)
[0] at settle (/Users/uddhavbhagat/Desktop/Projects/TuneIn/node_modules/axios/lib/core/settle.js:17:12)
[0] at IncomingMessage.handleStreamEnd (/Users/uddhavbhagat/Desktop/Projects/TuneIn/node_modules/axios/lib/adapters/http.js:236:11)
[0] at IncomingMessage.emit (events.js:322:22)
[0] at endReadableNT (_stream_readable.js:1187:12)
[0] at processTicksAndRejections (internal/process/task_queues.js:84:21)
[0] (node:12697) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 4)
The error you‘re getting is that the Promise (axios.get) does not have a catch.
Therefore when the api call results in an error, you are not handling it in any way. What about trying it the asynchronous way?
I would send the api call axios.get(‘URL‘, ...) and then handle the response with .then and .catch.
I would suggest the following:
axios.get('https://api.spotify.com/v1/search', { headers: { 'Authorization': keys.spotifyClientId } })
.then(response => {
const spotify_search_one = response.data;
}).catch(err => {
console.error(err);
})
This will ask the Spotify-API for the desired data and then execute anything you write in the .then when the API-call was successful. The variable response contains the data (in this case the search results) which you can get with response.data.
If the API-call fails everything in .catch will be called. You could print the error or handle it in any other way then.

Knexjs and es6 Try/Catch causing an Unhandled Promise Rejection Warning?

I've been working on a new application that uses PostgreSQL and Knexjs as a query builder, but have been running into an issue I'm not sure how to handle.
I have a route handler that looks like so:
export const getSingleUser = async(req, res) => {
let respObj = {
status: 'fail',
message: 'User does not exist'
};
try {
const user = await knex('users').where('id', req.params.id).first();
if (!user) {
res.send(respObj);
}
respObj = {
status: 'success',
data: user
};
res.send(respObj);
} catch(e) {
res.send(respObj);
}
};
It works great, until I throw a non-existent user ID into the mix. I assumed the catch statement would handle the error if no user is found for the query, but that doesn't seem to work, it just spits out the respObj in the try block. So I added an if statement to check if the user object doesn't exist, and thats when I received the warning below:
(node:25711) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at validateHeader (_http_outgoing.js:503:11)
at ServerResponse.setHeader (_http_outgoing.js:510:3)
at ServerResponse.header (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/express/lib/response.js:767:10)
at ServerResponse.send (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/express/lib/response.js:267:15)
at ServerResponse.send (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/express/lib/response.js:158:21)
at _callee3$ (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/src/controllers/userController.js:45:7)
at tryCatch (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/regenerator-runtime/runtime.js:65:40)
at Generator.invoke [as _invoke] (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/regenerator-runtime/runtime.js:303:22)
at Generator.prototype.(anonymous function) [as next] (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/node_modules/regenerator-runtime/runtime.js:117:21)
at step (/Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/src/controllers/userController.js:14:191)
at /Users/munsterberg/Sites/fullstack_workspace/esports-manager/services/project/src/controllers/userController.js:14:361
at <anonymous>
(node:25711) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:25711) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Can anyone provide more info on why this is happening, and whats the fix?
Work around
A response is sent twice in the try block if the user does not exist. This accounts for the error raised:
"Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client".
The unhandled promise rejection warning is being raised because if the res.send() call in the catch code block throws, the promise returned from calling getSingleUser gets rejected with the same error - implying there is no error handling in place for the returned promise (because isn't supposed to get rejected).
Directing the "user does not exist" case to the catch block, by throwing an error, could be a work around to avoid the issue in the first place. A cut-down example:
export const getSingleUser = async(req, res) => {
try {
const user = await knex('users').where('id', req.params.id).first();
if (!user) {
throw new Error(" user does not exist");
}
res.send( {
status: 'success',
data: user
});
} catch(e) {
// console.log(e); // debug if needed
res.send( {
status: 'fail',
message: 'User does not exist'
});
}
};

Categories