MAX_DIMENSIONS_EXCEEDED distancematrix error - google-distancematrix-api

I know that "MAX_DIMENSIONS_EXCEEDED" error showing when Your request contained more than 25 origins, or more than 25 destinations. But Just I want to know this limit is only for free api customer or it's for all?
I am using below google service
var service = new google.maps.DistanceMatrixService();

If you currently have the free plan you get a maximum of 25 origins OR 25 destinations per request. If you go above the free plan allowance you have to pay extra. So that limit is whether you pay or not.
The premium plan where you get a maximum of 25 origins AND 25 destinations per request is only available to users with premium plans prior to the latest price change. From what you have said, you can't have the premium.
See more here: https://developers.google.com/maps/premium/usage-limits

Heyo :)
I stumbled across this exact issue while creating a "medium-sized" MapsAPI Project.
Even though we had billing enabled and configured on Google, I had this status code show up.
You are allowed to pass max. 25 destinations and origins per request (like Do2 correctly said). But what if you have 150 Stores and more??
My idea was to split the requests into chunks and call the API server-side.
So i excluded the API Call in a PHP file and passed my data with AJAX (app.js <-> magic.php)
See my Workaround:
/* CLIENTSIDE app.js */
const getDistanceMatrix = (service, parameters) =>
new Promise((resolve, reject) => {
let paramString = JSON.stringify(parameters);
//console.log(paramString);
$.ajax({
type: "Post",
url: "/develope/kk-store-locator/magic.php",
data: {
daten: paramString,
},
success: function (response) {
//Wenn Query success
response = JSON.parse(response);
console.log(response);
const distances = [];
const results = response.rows[0].elements;
for (let j = 0; j < results.length; j++) {
const element = results[j];
var addressText = response.destination_addresses[j];
//const distanceText = element.distance.text;
//const distanceVal = element.distance.value;
const distanceObject = {
storeid: stores[j],
distanceText: addressText,
};
distances.push(distanceObject);
}
resolve(distances);
},
error: function (response) {
// Wenn Query failed = Promise revoked
responserr = JSON.parse(response);
console.log(responserr);
reject(response);
},
});
});
const distancesList = await getDistanceMatrix(service, {
origins: [origin],
destinations: destinations,
travelMode: "DRIVING",
unitSystem: google.maps.UnitSystem.METRIC,
});
// HIER Zurückgeben
distancesList.sort((first, second) => {
return first.distanceVal - second.distanceVal;
});
return distancesList;
}
SERVERSIDE (magic.php):
<?php
data = json_decode($_POST["daten"]);
$origin = $data->origins[0];
$destinations = $data->destinations;
//Variablendeklaration Request-String
$chunk_size = 24; //25 Stores
$dest_counter = sizeof($destinations); //StoreLength gesamt
$dest_chunkz = ceil($dest_counter / $chunk_size); //Aufrunden für Requestanzahl
$strings = [];
//Build String max.25 Destinations
$iter = 0;
for ($i = 0; $i < $dest_chunkz; $i++) {
for ($iter; $iter < $dest_counter; $iter++) {
$strings[$i] .= $destinations[$iter]->lat . "," . $destinations[$iter]->lng . "|";
$items = substr_count($strings[$i], '|');
if ($items == 25) { //Runtime-Limit (max. 25)
break;
}
}
}
//Call to Google Distanz-API
foreach ($strings as $string) {
$string = substr($string, 0, -1);
$latNlong_origin = $origin->lat . "," . $origin->lng;
$distance_data = file_get_contents('https://maps.googleapis.com/maps/api/distancematrix/json?&origins=' . urlencode($latNlong_origin) . '&destinations=' . urlencode($string) . '&key=' . $apiKey . '');
$distance_arr = json_decode($distance_data);
array_push($distance_copy, $distance_arr);
if ($distance_arr->status == 'OK') {
$destination_addresses = $distance_arr->destination_addresses;
$origin_addresses = $distance_arr->origin_addresses;
} else {
echo "<p>The request was Invalid</p>";
echo $distance_arr->status;
exit();
}
if ($origin_addresses == "" or $destination_addresses == "") {
echo "<p>Destination or origin address not found</p>";
exit();
}
}
=> remove duplicates, and return <=
I hope this brings the idea of the "workaround" a little closer - note that you always need billing enabled to work with all of the Google APIs
Have a nice Day :)

Related

Change options only if something changed via AJAX Response

I need your help concerning AJAX Responses with Symfony. On my page I have select options and want only refresh them, if anything in DB has changed. Now I'm loading every five seconds and checking if data count is different. But on the other hand users could also edit/rename old options. If I only check the count it's not possible to refresh the list. So how can I check if old response different than the new one?
Thanks in advance!!
(My code in JS as follows)
let Routing = require('../../vendor/friendsofsymfony/jsrouting-bundle/Resources/public/js/router')
let Routes = require('./js_routes')
Routing.setRoutingData(Routes)
let select_options = document.getElementById("person_names")
document.addEventListener('DOMContentLoaded', function (event) {
if(window.location.href.indexOf("entity=Person&action=new") > -1 || window.location.href.indexOf("entity=Person&action=edit") > -1){
let firstRequest = true;
let responseOld
window.setInterval(function () {
new Promise( function (resolve, reject) {
let url = Routing.generate('getNewPersonList')
let xhr = new XMLHttpRequest()
xhr.open('GET', url)
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
xhr.addEventListener('load', function (event) {
if (this.status === 200 && this.statusText === "OK"){
resolve(JSON.parse(this.responseText))
} else {
reject(JSON.parse(this.responseText))
}
})
xhr.send()
})
.then((response) => {
debugger;
if (firstRequest){
responseOld = response
firstRequest = false
// document.cookie = "Names=" + response + "; expires=Thu, 18 Dec 2019 12:00:00 UTC; path=/refreshNames";
console.log("first")
}
if (select_options.length !== response.length) {
console.log(select_options)
console.log(response)
// Drop old options
select_options.length = 0
// Fill it with new names
for (let index = 0; index < response.length; index++) {
let $option_element = document.createElement('option')
$option_element.value = response[index].id
$option_element.text = response[index].name
select_options.appendChild($option_element)
}
}
})
.catch((error) => {
console.log(error)
})
}, 5000)
}
})

Firefox addon for blocking url

with my extension i want to "block" some websites url and redirect to one url that i want whenever a user tries to join the blocked url.
Lets say that i want to "ban" facebook.com and if someone tries to go to facebook.com ... firefox addon should redirect him to www.google.com.
i have this code here
===============================================================================
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import('resource://gre/modules/Services.jsm');
var urls_block = [ //if urls ontain any of these elements they will be blocked or redirected, your choice based on code in observer line 17
'www.facebook.com'
];
var redir_obj = {
'www.google.com': 'data:text,' + escape('url_blocked that would have went to google')
}
var observers = {
'http-on-modify-request': {
observe: function (aSubject, aTopic, aData) {
console.info('http-on-modify-request: aSubject = ' + aSubject + ' | aTopic = ' + aTopic + ' | aData = ' + aData);
var httpChannel = aSubject.QueryInterface(Ci.nsIHttpChannel);
var requestUrl = httpChannel.URI.spec.toLowerCase();
for (var i=0; i<urls_block.length; i++) {
if (requestUrl.indexOf(urls_block[i]) > -1) {
//httpChannel.cancel(Cr.NS_BINDING_ABORTED); //this aborts the load
httpChannel.redirectTo(Services.io.newURI(redir_obj[urls_block[i]], null, null)); //can redirect with this line, if dont want to redirect and just block, then uncomment this line and comment out line above (line 17)
break;
}
}
},
reg: function () {
Services.obs.addObserver(observers['http-on-modify-request'], 'http-on-modify-request', false);
},
unreg: function () {
Services.obs.removeObserver(observers['http-on-modify-request'], 'http-on-modify-request');
}
}
};
function install() {}
function uninstall() {}
function startup() {
for (var o in observers) {
observers[o].reg();
}
}
function shutdown(aData, aReason) {
if (aReason == APP_SHUTDOWN) return;
for (var o in observers) {
observers[o].unreg();
}
}
==================================================================
but i dont know how to make it work or even if its the correct code to redirect "facebook" to "google"
Could someone help me with this to show me how can i pack it as a firefox extension???
Thanks a lot for your time reading.
Video demonstrating its working posted here: Firefox addon error in scratchpad
related topics:
https://stackoverflow.com/a/30928671/1828637
Why is this JavaScript page redirect so slow?

How many API Request is considered by Parse.com?

I have a cloud code written
Parse.Cloud.define("getApartmentVendorProduct", function(request, response) {
var isApartmentCallComplete = false;
var isVendorCallComplete = false;
var isProductCallComplete = false;
var result = {};
var apartmentQuery = new Parse.Query("Apartment");
apartmentQuery.find({
success: function(results) {
isApartmentCallComplete = true;
results.apartments = results;
}
});
var vendorQuery = new Parse.Query("Vendor");
vendorQuery.find({
success: function(results) {
isVendorCallComplete = true;
results.vendors = results;
}
});
var productQuery = new Parse.Query("Product");
productQuery.find({
success: function(results) {
isProductCallComplete = true;
results.products = results;
}
});
setInterval(function () {
if (isApartmentCallComplete && isVendorCallComplete && isProductCallComplete) {
response.success(results);
}
}, 50);
});
PS: I'm well aware that setInterval wont work on Parse.. This code is just for understanding.
In this cloud function i'm making 3 Query operation.
From my Android application i'm calling this cloud code.
Here is my question.
How many API request is this considered?
1) 3 API Request made by cloud code and 1 API Request made by Android - Total 4
2) Just 1 API Request made by Android. - Total 1
The option is 1 it makes 4 requests.
I tried with a sample code to test Burst Limit
Parse.Cloud.define("testBurstLimit", function(request, response) {
var globalI = 0;
for(var i = 0; i < 500; i++) {
var productQuery = new Parse.Query("Product");
productQuery.find({
success: function(results) {
console.log("success " + i + " " + globalI);
globalI++;
if (globalI == 250) {
response.success("success");
}
},
error: function(error) {
isApartmentCallComplete = true;
if (isApartmentCallComplete && isVendorCallComplete && isProductCallComplete) {
console.log(error.message + " " + error.code);
}
}
});
}
});
One thing strange i noticed is that. Parse doesn't calculate requests/second, instead it calculates in Requests per/min. Check the response from Parse when i perform the BurstLimit cloud code again and again
{"code":155,"error":"This application performed 1814 requests over the last 28s, and exceeded its request limit. Please retry in 32s"}

WP ajax always returns 0 even when using die

I am trying to use ajax the WP way and I cannot get a response back. If I use ajax manually and include the url to a php file it works fine. But I want to use ajax in wp the "proper" way.
Here is what I have.
add_action('wp_ajax_get_data', 'get_data');
function get_data(){
$group = $_GET['option_group'];
$data_table = 'tablename';
// Array to hold data
$bigArray = array();
// Variable to determine the select clause
$query = "SELECT * FROM $data_table WHERE `group` = $group ";
$datas = $wpdb->get_results($query);
foreach($datas as $data) {
array_push($bigArray, $data);
}
echo json_encode($bigArray);
//Don't forget to always exit in the ajax function.
die();
}
Then the request
jQuery('#new_service #service_option_group').on('change', function() {
// Ajax query to fetch the results
jQuery.ajax({
type: 'GET',
url: ajaxurl,
data: {
action: 'get_data',
data: jQuery('#service_option_group').serialize()
},
success: function(result) {
jQuery('#new_service #service_option_region').empty();
// need to add the default option back in
var option = document.createElement('option');
var select = document.getElementById('service_option_region');
option.text = 'Select an Option'
option.value = -1;
select.appendChild(option);
// Append on the events
for (var i = 0; i < result.length; i++) {
// create and append each element
var option = document.createElement('option');
option.text = result[i].title;
option.value = result[i].id;
var select = document.getElementById('service_option_region');
select.appendChild(option);
}
},
error: function(request, status, error) {
alert(request.responseText);
}
})
});

How to know if all uploads completed within a loop?

I have a code that works well for sending multiple files via ajax with FormData and XMLHttpRequest;
for (var i=0, j=this.files.length; i<j; i++) {
file = this.files[i];
var formdata = new FormData();
formdata.append("images[]", file);
var xhr = new XMLHttpRequest(),
upload = xhr.upload,
id = Math.floor((Math.random() * 100000));
upload.addEventListener("loadstart", function(e){
showUploadedItem(file, this.id);
});
upload.id = id;
upload.onprogress = function(e) {
var done = e.position || e.loaded, total = e.totalSize || e.total;
)
};
upload.onload = function(e) {
if (this.status == 200) {
console.log('');
}
};
xhr.onreadystatechange = function(e) {
if ( 4 == this.readyState ) {
console.log('');
}
};
xhr.open('post', '<?php echo Yii::app()->createUrl('url') ?>', true);
xhr.send(formdata);
}
I am sending each file as a new XMLHttpRequest object inside the loop, so I do not know when I'm getting all requests ending.
Can anyone help?
Take a look at the documentation for XMLHttpRequest.
There are a couple of options that I can think of. You could use the "loadend" callback for each of them and increment a variable outside of the loop and check for the total amount of requests that were sent in each one. Once the count reaches the total number of requests, you could perform any logic or call a function that would want to call.
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest?redirectlocale=en-US&redirectslug=DOM%2FXMLHttpRequest%2FUsing_XMLHttpRequest
Otherwise, setting the async parameter to false would work as well, but then you take a performance hit waiting for each one to finish before starting the others.
Based on your answer, my solution;
var x = 0;
var lenght = this.files.length;
for (var i=0, j=lenght; i<j; i++) {
// code here
var xhr = new XMLHttpRequest(),
// code here
xhr.onreadystatechange = function(e) {
if ( 4 == this.readyState && this.status == 200 ) {
x++;
if(x == lenght) {
window.setTimeout( function(){
alert('finish');
}, 1000 );
}
}
};
// code here
}
Though it is a trivial function, it works.

Resources