So I need to display multiple results of SQL query on the same component in AngularJS.
How would I do this? So far, I understood that component can treat only one http request as in here:
'use strict';
angular.module('cryostat', []).component('cryostat', {
templateUrl: 'cryostat/cryostat.template.html',
controller: function cryostatController($http) {
this.pageTitle = "NP04 Cryostat"
this.natalie = 1;
$http.get("cryostat.conn.php")
.then(function (response) {this.TT0101 = response.data.records;});
}
});
I understood that component can treat only one http request
This is not at all true. Where did you hear that? It is easy to make two requests simultaneously with $q.all():
var promiseOne = $http.get("query1.php");
var promiseTwo = $http.get("query2.php");
$q.all([promiseOne, promiseTwo]).then(function(resultArray) {
$scope.resultOne = resultArray[0];
$scope.resultTwo = resultArray[1];
});
Make use of $q.all() for your purpose.
var myData_One, myData_two;
var promises = [];
function promiseA() {
let deferred = $q.defer();
ajaxCall().then((response) => {
$scope.myData_One = response;
deferred.resolve();
}, (error) => {
deferred.reject(error);
});
return deferred.promise;
}
function promiseB() {
let deferred = $q.defer();
ajaxCall().then((response) => {
$scope.myData_two = response;
deferred.resolve(response);
}, (error) => {
deferred.reject(error);
});
return deferred.promise;
}
var promises = [promiseA(), promiseB()];
$q.all(promises).then((values) => {
//Do whatever you wish to with response data from both promises.
});
Related
I've this code to get nearby places and nearby beaches from a point, with Google maps. This is called from a Next.js component, via the useSWR hook.
All the data is returned correctly, but before first Axios call (const fetchNearbyPlaces = async (urlWithToken = null) => {...), I'm receiving this error in the console:
API resolved without sending a response for /api/google/places/33.807501/-78.70039, this may result in stalled requests.
I can't figure out what the error is, although there may be several because I'm a novice. I appreciate any suggestion.
const axios = require("axios");
const GetNearbyPlaces = async (req, res) => {
const {
latitude,
longitude,
} = req.query;
const radius = 50000;
const types = [
"airport",
"tourist_attraction",
"amusement_park",
"aquarium",
"art_gallery",
"bar",
"museum",
"night_club",
"cafe",
"restaurant",
"shopping_mall",
"store",
"spa",
];
function checkFunc(arr, val) {
return arr.some(arrVal => val === arrVal);
}
const url = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${latitude}%2C${longitude}&radius=${radius}&key=${process.env.CW_GOOGLE_MAPS_API_KEY}`;
const beachesUrl = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${latitude}%2C${longitude}&radius=${radius}&type=natural_feature&key=${process.env.CW_GOOGLE_MAPS_API_KEY}`;
try {
let results = [];
let beaches = [];
const fetchNearbyBeaches = async (urlWithToken = null) => {
await axios.get(urlWithToken ? urlWithToken : beachesUrl).then(data => {
beaches = [...beaches, ...data.data.results];
if (data?.data?.next_page_token) {
const newUrl = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=${process.env.CW_GOOGLE_MAPS_API_KEY}&pagetoken=${data.data.next_page_token}`;
setTimeout(() => {
fetchNearbyBeaches(newUrl);
}, 2000);
} else {
beaches.length > 5 && beaches.splice(5);
results.length > 5 && results.splice(5);
const finalResults = [...beaches, ...results];
finalResults.length > 10 && finalResults.splice(10);
return res.status(200).json({
data: {
results: finalResults,
},
success: true,
});
}
});
};
const fetchNearbyPlaces = async (urlWithToken = null) => {
await axios.get(urlWithToken ? urlWithToken : url).then(data => {
results = [...results, ...data.data.results];
if (data?.data?.next_page_token) {
const newUrl = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=${process.env.CW_GOOGLE_MAPS_API_KEY}&pagetoken=${data.data.next_page_token}`;
setTimeout(() => {
fetchNearbyPlaces(newUrl);
}, 2000);
} else {
const dirtyResultsWithDuplicates = [];
results.map(result => {
return types.map(type => {
if (checkFunc(result.types, type) && !result.types.includes("lodging")) {
dirtyResultsWithDuplicates.push(result);
}
});
});
const set = new Set(dirtyResultsWithDuplicates);
const filtered = Array.from(set);
results = filtered.length > 10 ? filtered.splice(10) : filtered;
return fetchNearbyBeaches();
}
});
};
fetchNearbyPlaces();
} catch (err) {
res.status(500).json({
message: err.message,
statusCode: 500,
});
}
};
export default GetNearbyPlaces;
The problem is with the backend application not the frontend component.
Nextjs expects a response to have been sent when the api handler function exits. If for example you have a databaseCall.then(sendResponse) in your api handler function what happens is that the handler function exits before the database returns.
Now this is not a problem if the database does return after that and sends the response, but it is if for example the database has an error. Because the handler function exits without a response already being sent Nextjs can't be sure that at that point there isn't a stalled request.
One way to fix this is by await-ing the db call(or whatever other async function you call) thereby preventing the handler function from exiting before some kind of response has been send.
The solution was added this object to mi API code.
export const config = {
api: {
externalResolver: true,
},
};
Documentation: https://nextjs.org/docs/api-routes/request-helpers
I accessed API to upload image and return the image URL with Vue app. I want to set API response value to imgUrl1 in data section. I' sure getting correct response in console but imgUrl1 is still empty. Anybody idea ?? Thank you so much !
Vue
data () {return
{
imgUrl1:'',→empty
}
},
methods: {
uploadFile1: function () {
var img_file1 = this.$refs.img1.files[0]
var params = new FormData()
params.append('image', img_file1)
params.append('client_name', this.tableSelected)
axios.post("http://127.0.0.1:5000/", params
).then(function (response) {
console.log(response.data)→image url exists
this.imgUrl1 = response.data
}).catch(function (error) {
for(let key of Object.keys(error)) {
console.log(key);
console.log(error[key]);
}
});
}
console.log(response.data)
https://storage.googleapis.com/dashboard_chichat/img/クライアント名/xxxxxxxxnQSkX6Wudy.jpg
try using arrow functions in your then callback so the value of this is your Vue component.
methods: {
uploadFile() {
...
axios.post('', params)
.then((response) => {
this.imgUrl1 = response.data
})
}
}
the equivalent of it without arrow functions is:
methods: {
uploadFile() {
...
const _this = this;
axios.post('', params)
.then(function (response) {
_this.imgUrl1 = response.data
})
}
}
I have a test to test my cloudflare worker that looks like this:
const workerScript = fs.readFileSync(
path.resolve(__dirname, '../pkg-prd/worker.js'),
'utf8'
);
describe('worker unit test', function () {
// this.timeout(60000);
let worker;
beforeEach(() => {
worker = new Cloudworker(workerScript, {
bindings: {
HTMLRewriter
},
});
});
it('tests requests and responses', async () => {
const request = new Cloudworker.Request('https://www.example.com/pathname')
const response = await worker.dispatch(request);
console.log(response);
// const body = await response.json();
expect(response.status).to.eql(200);
// expect(body).to.eql({message: 'Hello mocha!'});
});
});
In my worker I do something like this:
const response = await fetch(BASE_URL, request);
const modifiedResponse = new Response(response.body, response);
// Remove the webflow badge
class ElementHandler {
element(element) {
element.append('<style type="text/css">body .w-webflow-badge {display: none!important}</style>', {html: true})
}
}
console.log(3);
return new HTMLRewriter()
.on('head', new ElementHandler()).transform(modifiedResponse);
Now when i run my test I get this error message:
● worker unit test › tests requests and responses
TypeError: Cannot read property 'transform' of undefined
at evalmachine.<anonymous>:1:1364
at FetchEvent.respondWith (node_modules/#dollarshaveclub/cloudworker/lib/cloudworker.js:39:17)
What seems to be wrong?
HTMLRewriter i created looks like this:
function HTMLRewriter() {
const elementHandler = {};
const on = (selector, handler) => {
if (handler && handler.element) {
if (!elementHandler[selector]) {
elementHandler[selector] = [];
}
elementHandler[selector].push(handler.element.bind(handler));
}
};
const transform = async response => {
const tempResponse = response.clone();
const doc = HTMLParser.parse(await tempResponse.text());
Object.keys(elementHandler).forEach(selector => {
const el = doc.querySelector(selector);
if (el) {
elementHandler[selector].map(callback => {
callback(new _Element(el));
});
}
});
return new Response(doc.toString(), response);
};
return {
on,
transform
};
}
Since HTMLRewriter() is called with new, the function needs to be a constructor. In JavaScript, a constructor function should set properties on this and should not return a value. But, your function is written to return a value.
So, try changing this:
return {
on,
transform
};
To this:
this.on = on;
this.transform = transform;
whenever a user types anything into the textfield, an axios get request to the url
http://sandbox4.wootz.io:8080/api/data/1/action/?filter={id}like'%TE%' is made and it is supposed to return back all the filtered results based on the search(what user has typed) as a response. But currently rather than returning the filtered results as a response it is giving out all results(non-filtered results).
NOTE: I have tested the above mentioned URL through postman by making a get request and it gave out the filtered results perfectly.Why is the same not happening through my application code?plz help
getAsyncDataAction: debounce(function(name) {
if (!name.length) {
this.dataAction = [];
return;
}
this.isFetching = true;
api
.getSearchData(this.sessionData.key,`/action/?filter={id}like'%${name}%'`)
.then(response => {
this.dataAction = [];
response.forEach(item => {
this.dataAction.push(item);
});
console.log('action results are'+JSON.stringify(this.dataAction)) //displays all the results(non-filtered)
})
.catch(error => {
this.dataAction = [];
throw error;
})
.finally(() => {
this.isFetching = false;
});
}, 500),
api.js
import axios from 'axios';
const props = {
base_url: '/api/store',
search_url: '/api/entity/search',
cors_url: 'http://localhost',
oper_url: '/api'
};
axios.defaults.headers.get['Access-Control-Allow-Origin'] = props.cors_url;
axios.defaults.headers.post['Access-Control-Allow-Origin'] = props.cors_url;
axios.defaults.headers.patch['Access-Control-Allow-Origin'] = props.cors_url;
async function getSearchData(key, path) {
try {
console.log('inside getSearchData path value is'+path)
console.log('inside getSearchData and url for axios get is '+props.base_url + '/data' + path)
let response = await axios({
method: 'get',
url: props.base_url + '/data' + path,
headers: {'session_id': key}
});
if (response.status == 200) {
console.log(response.status);
}
return response.data;
} catch (err) {
console.error(err);
}
}
The problem is that you're not encoding the query string correctly. In particular, your % signs need to become %25
To do this, I highly recommend using the params options in Axios.
For example
async function getSearchData(key, path, params) { // 👈 added "params"
// snip
let response = await axios({
method: 'get',
url: `${props.base_url}/data${path}`,
params, // 👈 use "params" here
headers: {'session_id': key}
});
and call your function with
const params = {}
// check for empty or blank "name"
if (name.trim().length > 0) {
params.filter = `{id}like'%${name}%'`
}
api
.getSearchData(this.sessionData.key, '/action/', params)
Alternatively, encode the query parameter manually
const filter = encodeURIComponent(`{id}like'%${name}%'`)
const path = `/action/?filter=${filter}`
Which should produce something like
/action/?filter=%7Bid%7Dlike'%25TE%25'
async1.each(arr, function(arrayMember) {
orders.where('name', arrayMember).fetch({withRelated: ['allOrders']}).
then(function(dd2, callback) {
dd2 = dd2.toJSON();
var sendMemberOrder = {};
sendMemberOrder.name = dd2.name;
sendMemberOrder.lastOrder = dd2.allOrders.length;
res.send(sendMemberOrder);
});
}, function(err) {
if (err) {
console.log("err");
}
});
I'm trying to use Express's res.send() feature but given that I'm using async.each, I'm getting
headers already sent
error.
How can I pass the result of each iteration as an array when a request is being made?
Since you already use promises here, I would like to doscourage you from using async.js here. Your code is broken anyway as it does not call callback at all, and the callback parameter is declared on the wrong function. Instead you could try this:
app.get(your_route, function(req, res, next) {
// obtain arr
Promise.all(arr.map(function(arrayMember) {
return orders.where('name', arrayMember)
.fetch({withRelated: ['allOrders']})
.then(function(dd2) {
dd2 = dd2.toJSON();
return {
name: dd2.name,
lastOrder: dd2.allOrders.length
};
});
})).then(function(resultData) {
res.send(resultData);
}).catch(function(err) {
console.log(err);
next(err);
});
});