I am making API calls from my CRA (Create React App). Sometimes while opening a random page all of the API calls are showing the status of "pending" forever. When I refresh my page then, all the APIs work fine.
These are the details of the API in "pending" status.
const checkWelcomeRewardShown = async () => {
try {
if (localStorage.getItem("userType") === "student") {
let res = await axios.get(`${process.env.REACT_APP_BASE_URL}/api/gethasnotseenintro`);
if (res?.data?.status === "success" && res?.data?.notSeen) {
await axios.get(`${process.env.REACT_APP_BASE_URL}/api/getunlocktokenuser`);
await axios.get(`${process.env.REACT_APP_BASE_URL}/api/falsewhenfirstlogin`);
}
let response = await axios.get(`${process.env.REACT_APP_BASE_URL}/api/seenPopupForLinkedinAndFeedback`);
}
} catch (error) {}
};
useEffect(() => {
checkWelcomeRewardShown();
dispatch(showAllPopups());
}, [localStorage.getItem("user_id")]);
It is solved. There was an API in Backend that was failing and there was no logic for what should happen if it fails. This was like a global level API that was being used everywhere so when it failed, it kind of blocked the execution of the rest of the APIs. That's why all of them were showing "pending".
Related
I've set up a webhook with Stripe, which calls a serverless function when it's triggered.
The function is intended to update an entry in my database when it's called, suggesting that a user has signed up for a premium account.
When I run this locally, the webhook works perfectly. It triggers the API, updates the user and processes the payment.
However, when it gets run on live, I continually get a 308 error saying:
Redirecting to my-app-url.com
Here's the code for my function:
import { buffer } from "micro"
import { createClient } from "#supabase/supabase-js";
require("dotenv").config();
const stripe = require("stripe")(process.env.STRIPE_LIVE_KEY)
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET
const supabaseUrl = process.env.REACT_APP_SUPABASE_URL
const supabaseAnonKey = process.env.REACT_APP_SUPABASE_ANON_KEY
const supabase = createClient(supabaseUrl, supabaseAnonKey)
module.exports = async (req, res) => {
const signature = req.headers["stripe-signature"]
const reqBuffer = await buffer(req)
let event
try {
event = stripe.webhooks.constructEvent(reqBuffer, signature, endpointSecret)
} catch (err) {
console.log(err)
return res.status(400).send(`Webhook error: ${err.message}`)
}
if (event.type === "checkout.session.completed") {
console.log("Checkout completed!")
const userId = String(event.data.object.client_reference_id)
console.log(userId)
const { error } = await supabase.from('profiles').update({ premium: 'true' }).eq('id', userId)
if (error) {
console.log(error)
}
}
res.send({ received: true })
}
When I check my function logs, it just seems like it's not even firing / reaching my API at all - there's no logs.
Does anyone have any suggestions?
The problem is the default domain redirect in Vercel.
The recommended way is to redirect to www, so this is the format you should use:
Wrong: https://[YOUR_DOMAIN].com/api/endpoint
Right: https://www.[YOUR_DOMAIN].com/api/endpoint
Cheers
As the 308 error indicates, it looks like your server is receiving the webhook, but attempting to redirect it to another URL. It's possible that it's even the same URL, but over HTTPS.
Stripe can't follow redirects so this is a misconfiguration on your server's end. You have to give the exact URL for where your server expects to receive webhooks.
I built an app in Slack, that on interactions in Slack, will send an HTTP POST request to a URL. That URL is a Firebase Function that is triggered with an HTTP request.
The Firebase Function looks like this...
// process incoming shortcuts
exports.interactions = functions.https.onRequest(async (request, response) => {
response.send();
const payload = JSON.parse(request.body.payload);
functions.logger.log(payload);
if (payload.type === 'shortcut') {
functions.logger.log('Found a shortcut...');
const shortcuts = require('./shortcuts');
await shortcuts(payload);
} else if (payload.type === 'block_actions') {
functions.logger.log('Found a block action...');
const blockActions = require('./blockActions');
await blockActions(payload);
} else if (payload.type === 'view_submission') {
functions.logger.log('Found a view submission...');
const viewSubmissions = require('./viewSubmissions');
await viewSubmissions(payload);
}
functions.logger.log('Done with interactions.');
});
The problem is, is that Firebase is taking 5-10 seconds to respond, and Slack is expecting a response in 3 seconds.
So the app in Slack erroring out.
It turns out while I thought it would be useful to do a response.send() immediately when the function was called so that Slack had its instant response, I was then also inadvertently starting background activities in Firebase.
The line in the above Firebase docs that gave me the biggest clue was:
Background activity can often be detected in logs from individual invocations, by finding anything that is logged after the line saying that the invocation finished.
Which I found here... the function started, and completed, and then the code to open a modal began to be executed...
I then found in the Firebase docs
Terminate HTTP functions with res.redirect(), res.send(), or res.end().
So all I really had to do was move response.send() to the end of the function. Also I had to make sure that I had await statements before my async functions, so that async functions waited to be resolved before executing the final response.send()
// process incoming shortcuts
exports.interactions = functions.https.onRequest(async (request, response) => {
const payload = JSON.parse(request.body.payload);
functions.logger.log(payload);
if (payload.type === 'shortcut') {
functions.logger.log('Found a shortcut...');
const shortcuts = require('./shortcuts');
await shortcuts(payload);
} else if (payload.type === 'block_actions') {
functions.logger.log('Found a block action...');
const blockActions = require('./blockActions');
await blockActions(payload);
} else if (payload.type === 'view_submission') {
functions.logger.log('Found a view submission...');
const viewSubmissions = require('./viewSubmissions');
await viewSubmissions(payload);
}
functions.logger.log('Done with interactions.');
response.send();
});
The modal interaction response times in Slack are much quicker and usable now.
I am working on an application where I want to implement the message Inbox. I have created the message inbox using Angular8 and NodeJS REST API. Now I want to get the on inbox message in every 30 Second on the background when user login also it doesn't want to affecting the performance of the Angular app.
So I want to Implement the Web-worker with Angular8 to get the Data from NodeJS REST API but I am unable to create.
I have added following code in Angular 8 App
Add this code to app.component.ts
getWorker(token){
if (typeof Worker !== 'undefined') {
// Create a new
const worker = new Worker('../../web-worker/messenger.worker', { type: `module` });
worker.postMessage(token);
worker.onmessage = (e) => {
setTimeout(() => {
worker.postMessage(token)
}, 15000);
};
} else {
// Web Workers are not supported in this environment.
// You should add a fallback so that your program still executes correctly.
}
}
Created worker file with fetch
/// <reference lib="webworker" />
addEventListener('message', ({ data }) => {
const response = `worker response to ${data}`;
postMessage(response);
});
import { environment } from "src/environments/environment";
onmessage = (message:any) => {
fetch(environment.apiUrl +'messages/notification/1/1',
{ method:'GET',
headers:new Headers({
Authorization: `Bearer ${message.data}`
})
}
)
.then(response => {
return response.json()
})
.then(commits => {
// self.onmessage(message)
return commits
});
};
but it shows the type as fetch is should be show web worker Right?
Can anyone help me with this?
I'm trying to make POST request on front page via 'jquery ajax' to my server, and then with that data from front make POST request to outer server on my server. Using that final response I got from outer request, I wanna render new data into my front using ajax success function.
It seemed to be working well on local server, but when I deploy this project with heroku or azure, this whole process take 1000~2000ms and doesn't seem to be working at all.
what's wrong with my code?
I'm trying to build some detecting system that would notify users if there's a vacancy on wanted course. so I let user to pick a class and at the same time I call a function to check if there's a vacancy on that class via POST request to school server.
//index.html
//in front page, when user pick a course to start observing, I send POST to my server
function scanEmpty(data,cn,elem){
$.ajax({
url: './getLeftSeat',
crossDomain: true,
type: 'POST',
data: data+`&cn=${cn}`,
success: function (data) {
alert('got!')
}
})
}
//app.js
// when I get POST from my server I call scanEmpty()
app.post('/getLeftSeat', async (req,res) => {
scanEmpty(qs.stringify(req.body), req.body["cn"], () => {res.json({success: true})})
})
// and that is like this
const scanEmpty = async(data, CN, cb) => {
if(await parseGetLeftSeat(await getData(data), CN)) cb()
else {
await scanEmpty(data,CN,cb)
}
}
// send POST to school server and get response using axios
async function getData(data) {
return await axios.post(school_server_url, data, {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'});
}
// it's just parsing and get data that I want
const parseGetLeftSeat = async (res, CN) => {
return new Promise((resolve, reject) => {
const $ = cheerio.load(res.data);
$("#premier1 > div > table > tbody > tr > td").each((i, e) => {
if (e.firstChild && e.firstChild.data == CN && e.next) {
const tmp = e.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next.firstChild.data.split('/')
resolve(Number(tmp[1].trim()) - Number(tmp[0].trim()) < 1 ? false : true)
}
})
})
}
It works alright though takes 1000~2000 ms when actually on deploy server while it takes 100~200 ms on local server. I tested some codes and it looks like axios.post() is the one. but even if I change it to node-fetch, the result was the same. I really don't know what to do.
In a NodeJS v10.x.x environment, when trying to create a PDF page from some HTML code, I'm getting a closed page issue every time I try to do something with it (setCacheEnabled, setRequestInterception, etc...):
async (page, data) => {
try {
const {options, urlOrHtml} = data;
const finalOptions = { ...config.puppeteerOptions, ...options };
// Set caching flag (if provided)
const cache = finalOptions.cache;
if (cache != undefined) {
delete finalOptions.cache;
await page.setCacheEnabled(cache); //THIS LINE IS CAUSING THE PAGE TO BE CLOSED
}
// Setup timeout option (if provided)
let requestOptions = {};
const timeout = finalOptions.timeout;
if (timeout != undefined) {
delete finalOptions.timeout;
requestOptions.timeout = timeout;
}
requestOptions.waitUntil = 'networkidle0';
if (urlOrHtml.match(/^http/i)) {
await page.setRequestInterception(true); //THIS LINE IS CAUSING ERROR DUE TO THE PAGE BEING ALREADY CLOSED
page.once('request', request => {
if(finalOptions.method === "POST" && finalOptions.payload !== undefined) {
request.continue({method: 'POST', postData: JSON.stringify(finalOptions.payload)});
}
});
// Request is for a URL, so request it
await page.goto(urlOrHtml, requestOptions);
}
return await page.pdf(finalOptions);
} catch (err) {
logger.info(err);
}
};
I read somewhere that this issue could be caused due to some await missing, but that doesn't look like my case.
I'm not using directly puppeteer, but this library that creates a cluster on top of it and handles processes:
https://github.com/thomasdondorf/puppeteer-cluster
You already gave the solution, but as this is a common problem with the library (I'm the author 🙂) I would like to provide some more insights.
How the task function works
When a job is queued and ready to be executed, puppeteer-cluster will create a page and call the task function (given to cluster.task) with the created page object and the queued data. The cluster then waits until the Promise is finished (fulfilled or rejected) and will close the page and execute the next job in the queue.
As an async-function is implicitly creating a Promise, this means as soon as the async-function given to the cluster.task function is finished, the page is closed. There is no magic happening to determine if the page might be used in the future.
Waiting for asynchronous events
Below is a code sample with a common mistake. The user might want to wait for an external event before closing the page as in the (not working) example below:
Non-working (!) code sample:
await cluster.task(async ({ page, data }) => {
await page.goto('...');
setTimeout(() => { // user is waiting for an asynchronous event
await page.evaluate(/* ... */); // Will throw an error as the page is already closed
}, 1000);
});
In this code, the page is already closed before the asynchronous function is executed. To correct way to do this would be to return a Promise instead.
Working code sample:
await cluster.task(async ({ page, data }) => {
await page.goto('...');
// will wait until the Promise resolves
await new Promise(resolve => {
setTimeout(() => { // user is waiting for an asynchronous event
try {
await page.evalute(/* ... */);
resolve();
} catch (err) {
// handle error
}
}, 1000);
});
});
In this code sample, the task function waits until the inner promise is resolved until it resolves the function. This will keep the page open until the asynchronous function calls resolve. In addition, the code uses a try..catch block as the library is not able to catch events thrown inside asynchronous code blocks.
I got it.
I was indeed forgetting an await to the call that was made to the function I posted.
That call was in another file that I use fot the cluster instance creation:
async function createCluster() {
//We will protect our app with a Cluster that handles all the processes running in our headless browser
const cluster = await Cluster.launch({
concurrency: Cluster[config.cluster.concurrencyModel],
maxConcurrency: config.cluster.maxConcurrency
});
// Event handler to be called in case of problems
cluster.on('taskerror', (err, data) => {
console.log(`Error on cluster task... ${data}: ${err.message}`);
});
// Incoming task for the cluster to handle
await cluster.task(async ({ page, data }) => {
main.postController(page, data); // <-- I WAS MISSING A return await HERE
});
return cluster;
}