I'm working on an AngularJS enhancement of a Wordpress website. I'm using the WP-API (v2) plugin to create custom endpoints and then consuming them on front end using Angular $http service.
Here's a code sample of the angular request:
function getData(slug) {
return $http.get(endpoints.specialData.replace(':slug', slug)).then(function (response) {
var data = response.data || {};
return data;
}, function (response) {
return response;
});
}
When I visit the page making this call I can see the time for this XHR (via Chrome dev tools) is about 4.5 seconds.
If I hit the same endpoint URL directly in the browser it returns the JSON result in 900ms. The endpoint URL is defined using a relative path (/path/relative/from/site/root) rather than the full http:// path, if that makes any difference.
Any ideas why it would take so much longer via Angular?
Debugging perf is quite particular, so all I can do is help you on your journey. You might want to take a look at troubleshooting the request using the Network tab in DevTools, and figure out what exactly is causing the slowdown. Read this article fully from Google: https://developers.google.com/web/tools/chrome-devtools/profile/evaluate-performance/timeline-tool
TL;DR If you see lot of green in your request, it's most likely a server issue, if it's blue, you're sending over too many bytes and need to optimize your JSON.
From there you can start narrowing it down.
Good luck!
Related
I am new to API usage. I have properly managed to utilize Google Page Insights V.5 API through javascript code, but I cannot for the life of me succeed in doing so for GTMetrix. It seems the only information relating to GTMetrix API & Javascript is a link to the RapidApi website. I simply wish to achieve the same simple retrieval of data from GTMetrix as I have from Google. Is this possible?
Am I simply structuring my request incorrectly when I set it as:
https://gtmetrix.com/api/0.1/?login-user=myemail#email.com&login-pass=MyRanDomApIKeY&location=2&url=https://sitetotest.com
Because when I set my Google Page Insights Request URL as the following it works.
https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=https://websitetotest.com&category=performance&strategy=desktop&key=MyRanDomApIKeY
The below code works for Google Page Insights and I am even able to retrieve JSON data in a browser window with a URL such as:
<div id="firstmetric"></div>
<br>
<div id="domSize"></div>
<button>Click Me</button>
<script>
$('button').click(function(){
var baseUrl = "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=";
var fieldUrl = "https://websitetotest.com";
var trailing = "&category=performance&strategy=desktop&key=MyRanDomApIKeY";
$.getJSON(baseUrl + fieldUrl + trailing, function(data){
console.log(data);
var item = data.lighthouseResult.categories.performance.auditRefs[0].weight;
var domSize = data.lighthouseResult.audits['dom-size'].displayValue;
$("#firstmetric").html( item );
$("#domSize").html( domSize );
});
});
I truly need it spelled out for me because anything less is going to lead me to ask follow up questions and put us in a tail spin. :/
As a newbie, JSFiddle has been a life saving resource for testing and trying, breaking, and building in my learning process. If it wouldn't be too much to ask for, a fiddle would help me get my brain around things.
The parameters that you are using: login-user and login-pass refer to HTTP authentication on the page you are analyzing (as in, GTmetrix will pass these parameters on your analysis) not your GTmetrix API credentials.
The authentication used for the GTmetrix API is your e-mail for the username and your API key as the password, as pointed out by the API docs.
Another thing to keep in mind is that GTmetrix will not allow you to do API calls through your web application frontend, since they disallow CORS requests. If you do it through your Web application on a normal website, you would be exposing your GTmetrix API key, which is probably not a good idea.
So, you would then do it through your backend code. For example if done through Node JavaScript:
fetch("https://gtmetrix.com/api/0.1/locations", {
headers: new Headers({
"Authorization": 'Basic ' + btoa("[YOUR E-MAIL]" + ":" +"[YOUR API KEY]"),
}),
}).then(res => res.json())
.then(response => console.log(response));
would print me the array of locations.
Note that whichever backend code you choose, you need to add the basic authorization header request for you API call and encode it properly (that is what the btoa function call does).
I can't for the life of me figure this out, it seems like it should be straight forward but it's just not clicking.
I have an ES6 app that I created using create-react-app. I've got all the templates and layouts set up for the project and came to trying to pull in data from an API that I want to sit inside the app - like a botched MVC where React handles the views and I run the models and controllers in PHP.
So I have a function in one of my components that I want to fetch some data. I use the fetch() function (I know this isn't yet compatible with a number of browsers but that's a problem for another day) to fetch a relative path from the component to the model I want to load, however the fetch function treats my path as a call to the base URL followed by the request. So with the site running on localhost:3000, I run the following code in my getData() function...
let test = fetch('../models/overall-stats.php').then(function(response) {
console.log(response);
return response;
});
...the URL that fetch hits is then http://localhost:3000/models/overall-stats.php which simply resolves back to the index.html file and loads the app, rather than the PHP file I'm requesting.
If I need to hit that PHP file to get my data, am I wrong in using fetch? Or am I just using it incorrectly? If I shouldn't be using fetch what's a better approach to this problem I'm having?
When I run this on an apache server (after building and deploying) I can get the fetches to work fine (apache recognizes the structure of the URL and hits it as I am expecting) and I hit the file no issues, but I need to be able to work in a local development environment and have the same functionality. The app will end up being deployed live on an apache server.
Any help would be greatly appreciated.
I knew after sleeping on this it would be very straight-forward... I simply had to move my models and controllers into the public directory for them to be accessible. I'll be putting in authentication to the models so that they can't be hit directly, but only through GET requests.
Why don't you just use something like ${baseUrl}/models/... ?
Also for solving browsers problem with fetch you can import the Polyfill or simply use axios (my choice)!
Maybe you can try to use ajax to get or post the data from server, just like this:
$.ajax({
url: '../models/overall-stats.php',
data: {
},
type: 'GET',
dataType : 'json',
success : function(res){
let obj = parseJSON(res)
}
})
or add this on top in your php file because the CORS :
header('Access-Control-Allow-Origin: *');
I've a MPA(Multiple page application). published for Android and iOS. It simply changes the page when user want to navigate to other page(view). All things are working fine. I want to implement some backend sync features. Problem is, I make Ajax request silently in background and user can change page anytime so app can lose reference of Ajax call which is highly important for keeping track of synced data.
Is there any plugin that can make http request on native code level or some other work around.
Have a look at cordova-plugin-http, it is a native plugin that executes all HTTP requests on a background thread.
Installation:
cordova plugin add cordova-plugin-http
Example POST request:
cordovaHTTP.post("https://google.com/", {
id: 12,
message: "test"
}, { Authorization: "OAuth2: token" }, function(response) {
// prints 200
console.log(response.status);
try {
response.data = JSON.parse(response.data);
// prints test
console.log(response.data.message);
} catch(e) {
console.error("JSON parsing error");
}
}, function(response) {
// prints 403
console.log(response.status);
//prints Permission denied
console.log(response.error);
});
There is no OOB way to do this. You can use something like the Cordova HTTP plugin to move HTTP requests to the native side, which will continue to execute across multiple pages, but it won't know what to do with the response once the response comes back if the user navigated to another page.
If your processing really is all background and doesn't truly need any JavaScript post-processing, you could try to look into something like the cordova-plugin-background-download - that basically executes a GET request in the background and saves the result where you tell it. It only supports GET, but it can work even if your whole app is put into the background.
If you need post-processing or non-GET requests, you can consider implementing your logic in native code in a plugin (perhaps using one of the HTTP plugins for Cordova to help with the actual network marshalling).
It'd be awesome if Cordova could support something like service workers, and I've been looking into that here and there. There's an old implementation for iOS but it doesn't seem to work anymore (and may not really be workable without extensive changes): cordova-plugin-serviceworker.
One other option would be to make your app a pseudo-SPA with some iframes. Have an iframe doing your requests and processing, and create interaction between the content iframe as needed. But that isn't trivial either.
I am making an language app that needs audio as well as visual translations. I thought of using Google Translate API, but according to this SO post, it appears that "The explanation is that Google restricts the usage of this service."
But this SO post, Google Text-To-Speech API, says I can use tl and q params, like http://translate.google.com/translate_tts?tl=zh-CN&q=Hello to return audio. This gives me a weird transliteration in Chinese of "Hello", which says "Ha Low" instead of "Ni Hao".
The user also states that "it will automatically generate a wav file which you can easily get with an HTTP request". When I GET using jsonp (need to use this because $.get() or non-jsonp requests have origin blocked) I get the following unreadable error:
Code:
var theApp = angular.module('myApp', []);
theApp.controller('APICtrl', ['$scope', '$http',
function($scope, $http) {
var httpRequest = "http://translate.google.com/translate_tts?tl=" + "zh-CN" + "&q=" + "Hello";
$http.jsonp(httpRequest)
.success(function(data) {
console.log(data);
}
);
}
]);
So my question is... is there a standard endpoint for Google translate API to access audio files? If not, what is a good way to do this that works?
This is a late response...
I would suggest using Jquery (or vanilla JavaScript) to do this instead of putting it in your app's controller. The URL you provided is fine, but now you need to set the Referer and User-Agent headers before you make the request.
You can use Jquery.get() to download the mp3 from Google's TTS API (you have to set the headers!). Then, you can create an HTML5 Audio object out of the data returned by Jquery in the #success method, and play that.
The response size for one-word queries like Hello are around 2-3kb, plenty small enough. Google's API is also incredibly fast, so with those two factors combined I wouldn't worry about performance at all. Keep in mind that the browser will also cache the audio file, so any subsequent 'hovering over words' will use the cached version and not send another request.
I'm building a prototype Angular app, using Parse as a temporary RESTful back end (Until the real restful backend is completed)
I've setup a Factory with $resource() but I'm constantly getting a 401 unauthorized.
Right now my factory looks like this (APPIDKEY AND APIKEY are redacted of course)
app.factory('eventFactory', ['$resource', function($resource){
return $resource('https://api.parse.com/1/classes/Events',{},
{headers:{"X-Parse-Application-Id": "APPIDKEY",
"X-Parse-REST-API-Key": "APIKEY"}});
}
]);
I've also tried writing the $resrouce like this.
$resource('https://myAppID:javascript-key=myJavaScriptKey#api.parse.com/1/classes/Events');
But that also returns a 401. however if I copy and paste that URL into my browser the screen prints out all the objects in the request.
I've done extensive googling and read the $resource docs many times but I still can't quite figure this out. I'm thinking it has to do with Cross-Origin policy but the parse documentation says
'For Javascript usage, the Parse Cloud supports cross-origin resource sharing, so that you can use these headers in conjunction with XMLHttpRequest.' So I'm kinda stumped.
Any help is much appreciated. Thanks!
Adding these two lines inside my module.config function fixed it.
$httpProvider.defaults.headers.common['X-Parse-Application-Id']="APPIDKEY"
$httpProvider.defaults.headers.common['X-Parse-REST-API-Key']="RESTAPIKEY"
where APPIDKEY and RESTAPIKEY equal the keys provided from Parse.com