Unhandled promise rejection stripe paymentIntent example - javascript

I'm trying to setup a stripe payment app using node and express, following the example here:
https://stripe.com/docs/payments/accept-a-payment#web
I created the route in my server side app code as indicated, and inserted the client-side code in my html file. I'm trying to create the app without a template engine, just html/css/javascript/node.
var response = fetch('/secret').then(function(response) {
return response.json();
}).then(function(responseJson) {
var clientSecret = responseJson.client_secret;
// Call stripe.confirmCardPayment() with the client secret.
});
I'm getting the following error:
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().
I'm new to promises and not sure what the syntax with this code should be. Can I add
promise1.catch((error) => {
console.error(error);
});

Yes, adding a catch method at the end would catch the error(rejected Promise). What you suggested would work.
var response = fetch('/secret').then(function(response) {
return response.json();
}).then(function(responseJson) {
var clientSecret = responseJson.client_secret;
// Call stripe.confirmCardPayment() with the client secret.
}).catch(function(err) {
// Handle error
});

Related

Cannot catch errors generated by fetch

In the try-catch syntax, I want to use fetch to catch errors when aborting while waiting.
I get an error in the console even though I describe it as follows
JavaScript
controller = new AbortController();
const signal = controller.signal;
try {
const data = await fetch(url, { signal })
} catch(e) {
return
}
console
Uncaught (in promise) DOMException: The user aborted a request.
The same problem occurred when I used promise chain.

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();

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.

how to change the function declaration to change the promise handling in node.js?

I am new to node.js & am using below code to download a csv file from GCS bucket to local folder.
// function to download file from GCS bucket
async function downloadFile(bucketName, srcFilename, destFilename) {
// Imports the Google Cloud client library
const {Storage} = require('#google-cloud/storage');
// Creates a client from a Google service account key.
const storage = new Storage({keyFilename: "keyFile.json"});
/**
* TODO(developer): Uncomment the following lines before running the sample.
*/
// const bucketName = 'Name of a bucket, e.g. my-bucket';
// const srcFilename = 'Remote file to download, e.g. file.txt';
// const destFilename = 'Local destination for file, e.g. ./local/path/to/file.txt';
const options = {
// The path to which the file should be downloaded, e.g. "./file.txt"
destination: destFilename,
};
// Downloads the file
await storage
.bucket(bucketName)
.file(srcFilename)
.download(options);
console.log(
`gs://${bucketName}/${srcFilename} downloaded to ${destFilename}.`
);
// [END storage_download_file]
}
// call downloadFile function
downloadFile('temp_bucket123','test_data.csv','./gcs_download/test_data.csv')
This code gives below error:
(node:10708) 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:10708) [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.
Do i need to re-write the function in a different way?
For async operation you should add a fallback if any error occurs, you can add try/catch block inside your method
async function downloadFile(bucketName, srcFilename, destFilename) {
// Imports the Google Cloud client library
const {Storage} = require('#google-cloud/storage');
// Creates a client from a Google service account key.
const storage = new Storage({keyFilename: "keyFile.json"});
/**
* TODO(developer): Uncomment the following lines before running the sample.
*/
// const bucketName = 'Name of a bucket, e.g. my-bucket';
// const srcFilename = 'Remote file to download, e.g. file.txt';
// const destFilename = 'Local destination for file, e.g. ./local/path/to/file.txt';
const options = {
// The path to which the file should be downloaded, e.g. "./file.txt"
destination: destFilename,
};
// Downloads the file
try {
await storage
.bucket(bucketName)
.file(srcFilename)
.download(options);
console.log(
`gs://${bucketName}/${srcFilename} downloaded to ${destFilename}.`
);
} catch (err) {
console.log('Some error occured', err)
}
// [END storage_download_file]
}
It appears that something inside of downloadFile() is creating an error that results in a rejected promise being returned from downloadFile(). That warning is because you have no error handling for that and unhandled rejections are considered evil. As the error says, in the future they may even automatically terminate your node.js process.
downloadFile('temp_bucket123','test_data.csv','./gcs_download/test_data.csv').then(() => {
console.log("done with download now");
}).catch(err => {
console.log(err);
});
All async functions that have any way to possibly reject their promise must have an error handler on them such as .catch() or with try/catch if using await to call the function.
You can also catch errors at the source and make sure that downloadFile() can't reject its promise. Either way, you have to catch the error somewhere and not let a rejected promise go unhandled. The designers of both promises and node.js have decided that an unhandled rejected promise should be just about akin to an unhandled exception (since they are logically pretty similar - a rejected promise being an exception for asynchronous code).

Exchanging authorization code for access token with googleapis package in Node

I'm trying to implement a google sign-in for a server-side NodeJS application that needs googledrive access, and can't get the 'googleapis' google object to exchange the authorization code for an actual access token.
There's google documentation for what I want to do here, but step 7, which is where I'm stuck, is described in Java and Python, and so the NodeJS google object isn't present. I've also followed the nodeJS quickstart here, but many of the steps for authentication are different. Namely, I can't make a google.auth.OAuth2 object the same way because the credentials for my application differ in format from the example's (they don't have redirect uris)
This is where I've got it:
const fs = require('fs');
const { google } = require('googleapis');
formAuthClient('<PastedAuthCodeFromFrontEnd>');
async function formAuthClient(code) {
// reads credentials from file
const credentials = await readFile('./client_secret.json').then(JSON.parse);
// cannot read redirect_uris like in NodeJS quickstart because these do not exist.
// Also, no credentials.installed, it's credentials.web
const { client_secret, client_id } = credentials.web;
const oAuth2Client = new google.auth.OAuth2( // form authObject
client_id, client_secret
);
console.log(oAuth2Client);
const token = await oAuth2ClientGetToken(oAuth2Client, code).catch(console.err);
oAuth2Client.setCredentials(token);
return oAuth2Client;
}
// just an async wrapper for fs.readFile
function readFile(file) {
return new Promise((resolve, reject) => {
fs.readFile(file, (err, content) => {
if (err) reject(err);
resolve(content);
});
})
}
// just an async wrapper for oAuth2Client.getToken
function oAuth2ClientGetToken(oAuth2Client, code) {
return new Promise((resolve, reject) => {
oAuth2Client.getToken(code, (err, token) => { // errors out here
if (err) reject(err);
resolve(token);
});
});
}
Running this code first prints the oAuth2Client object, and then gives me the following error:
OAuth2Client {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
transporter: DefaultTransporter {},
credentials: {},
certificateCache: {},
certificateExpiry: null,
certificateCacheFormat: 'PEM',
refreshTokenPromises: Map {},
_clientId: '<probablySecretClientID>.apps.googleusercontent.com',
_clientSecret: '<defSecretClientSecret>',
redirectUri: undefined,
eagerRefreshThresholdMillis: 300000
}
(node:16186) UnhandledPromiseRejectionWarning: Error: invalid_grant
at Gaxios.request (/home/miko/node/clouds/api/node_modules/gaxios/build/src/gaxios.js:70:23)
at processTicksAndRejections (internal/process/task_queues.js:89:5)
at async OAuth2Client.getTokenAsync (/home/miko/node/clouds/api/node_modules/google-auth-library/build/src/auth/oauth2client.js:119:21)
(node:16186) 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:16186) [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
Ideally, I'd want the top function to return a fully authenticated client object that I can later use to access google drive apis
I came up with a solution here https://github.com/googleapis/google-api-nodejs-client/issues/1951
For all thows that come after me - Resolution
Prerequisites
If you have the same setup as me where your performing the exchange for to token not in the frontend browser react code but in a back end setup. I did the following things which seems to resolve the issue.
1> Add the secondary hostname/port in the Google Cloud platform > APIs& Services > Credentials> (your oauth ClientID.) > Authorised JavaScript origins. with your web apps URI.
for example, if you have localhost:3000 serving your react code and localhost:3002. You need to ad both. This applies to your production setup as well.
2> The authorization code is one time use only. Once you use it, if your did not store the refresh token/access token. You need to ask the user to auth again. It gives the precise same message.
3> There seems to be a time out on how long you can hold the Authorization token. Google can answer this better than me, however I noticed I got the same error if I stored a working legitimate Authorization token for more than an hour and it gave me the same message as above.
My advise is send back better erroring than data: { error: 'invalid_grant', error_description: 'Bad Request' },
Since all the above scenarios seem to have caused the same error. It was hard for me to debug.

Categories