AngularJS delayed HTTP POST to PHP - php

I'm using the http service in AngularJS to make requests to my PHP API. It's a Phonegap iOS app, using AngularJS as the main framework.
In one call, I'm using the Facebook Javascript API to get the friends list of a user, encode that and send it to my API, match the emails to a list of our app users, then send the data back to the app.
I do exactly the same thing with the contacts from the phone, which I access using Phonegap.
Using console.log() I've confirmed that loading the contacts and facebook friends data from the device take less than a second.
The problem is mapping the Facebook friends list via the API takes about 20 seconds, but contacts only takes about 2 seconds.
I've manually forced the facebook list to be empty, var friends = [], and the process is nearly instant, but if I send 1 or 300 facebook contacts it gets really slow.
I've check the code on the live server by processing it with hard coded data and it takes about 0.01 seconds (so no HTTP POST, just the php logic).
I've also placed console.log() commands before the http.post() and during the success function:
console.log('http.post started');
$http.post(
$rootScope.api_url + '/friends/map/',
{values: hashes.values},
).success(function(data,status,headers,config){
console.log('http.post finished');
// process data
}).error(function(data,status,headers,config){
// log error
});
And in addition to that used PHP error_log to tell me when the start of the PHP processing occurs, and just before the result is returned:
<?php
// includes
require_once("../../../configs/config.".get_current_user().".php");
function process_request() {
error_log('started processing');
// decode POST data, work out API method etc
$return_data = $caseObject->process_data( $method, $arr_rest_data, $arr_req_data, $extra_data );
error_log('data processed');
return $return_data;
}
echo GibberishAES::enc( json_encode( process_request() ), IOS_API_PASSPHRASE );
?>
So that gives me a log before the Javascript sends the data, before and after the PHP processes it and after the Javascript receives a response.
Watching the logs get output, the 20s delay is between the following:
console.log('http.post started');
error_log('started processing');
So the delay seems to be in the upload. No data has been AES decoded by that point, and I've checked and the facebook data is an encoded string about 17k characters long, and the contacts data is 22k characters long. So it's not the size of the post, at least I don't think.
To summarise, I've got an http.post request in AngualrJS that is taking about 20s, very similar to another request that takes around 2s, the PHP code itself executes in under 1 second, and the delay seems to be between the start of the javascript http.post call and the beginning of the php processing code.
Any one know how I can work out what is causing the delay? Where should I be looking to narrow this down?

For anyone landing here with a similar issue:
The delay seems to be related with $http's request pre-processing and internal handling.
Using "plain old" XHR (eliminating $http) could speed things up considerably (at the cost of lost functionality and Angular-integration, of course).

Related

PHP request user data during execution of a script

I have a problem and I do not know how to solve it. I am working with PHP and the TDLib library to manage the Telegram API, for this, I make asynchronous calls through the JSON interface:
https://core.telegram.org/tdlib/getting-started#tdlib-interface
The Telegram API works through updates. The program receives the Telegram updates that must be answered properly in the order they are received. For this, I have a script with a 'while' cycle that works correctly for me. Here is an example of the algorithm:
void *client = td_json_client_create();
// somehow share the client with other threads, which will be able to send requests via td_json_client_send
const double WAIT_TIMEOUT = 10.0; // seconds
int is_closed = 0; // should be set to 1, when updateAuthorizationState with authorizationStateClosed is received
while (!is_closed) {
const char *result = td_json_client_receive(client, WAIT_TIMEOUT);
if (result) {
// parse the result as JSON object and process it as an incoming update or an answer to a previously sent request
}
}
td_json_client_destroy(client);
Well, the problem is that at any given time the update status of the API is "Waiting for phone number", at which time the user should be asked for the phone number. Subsequently, after several update states, Telegram sends a code to that phone number, so again my application must request the user to enter the received code when the status of the API is "Waiting for the code".
For this, I programmed two forms, one to request the phone number and another to request the code. The problem is that the forms are not shown until the script finishes, which does not help.
I tried to handle the flow of the script with break or return as the case may be, and this time I get the forms displayed at the right time, but the expected execution of the script ends, after sending the forms it becomes to execute all the code from the beginning, restarting the variables.
Anyway, I hope I have explained correctly and so that someone can give me better advice because I am really lost.

WordPress admin-ajax - defer actions until after response sent

I am using admin-ajax.php to respond to requests from JavaScript.
When I've pulled together the data I want and returned my response I also need to send some data to an external API and send an email to the user. Both of these things take a little bit of time.
I was hoping I could do something like this which would return the JSON response via AJAX before setting off the actions so they could essentially happen in the background after the response was back with the user:
function my_ajax_action() {
//process the $_REQUEST ajax data here
echo json_encode($results);
do_action('request_successful', $results);
wp_die();
}
...but it is obviously waiting to complete the actions before it dies (as PHP is not async) and the AJAX request doesn't complete until the response is provided.
Are there any known methods to defer these actions until after the response has been fully sent? The two functions attached to these actions are not required to deliver the response and are just adding a couple of seconds to the amount of time it takes for the results to show in the user's browser.
I am guessing I could store them in a cron job to happen very soon after but I feel it's likely that someone has already solved this issue in a better way.
thanks
Aaron
it could be related to PHP session locking and if you already have a script using session data, then the later script that will also request session data access will be put on hold until the initial script is done. Read more how to avoid it: http://konrness.com/php5/how-to-prevent-blocking-php-requests/

Execute php after 10s non blocking

Building a Facebook application and due to Facebook rules i must wait 10 seconds before executing a posting of user action.
This can be done with JavaScript also but have found the php sdk more precise.
My question is, What is the best and most accurate way of delaying the execution of code 10s
$response = $facebook->api(
'me/video.watches',
'POST',
array(
'tv_show' => "$permalink"
)
);
Using sleep(10); will block the entire page from loading. What is the correct solution here ?
This can be done by creating a database table and feed your database with records to be sent as post.
Create a cron at your server that reads the unprocessed records and create a facebook post to desired user.
What you want is some form of asynchrones processing. There are a number of different approaches you could take.
Write 'jobs' to a file, table in database, etc. and have a cronjob handle them.
Fork your PHP process, serving the response to the user in the 'parent' process and posting to Facebook in the 'child' proces.
Start a new process and detach it. (exec('php postToFacebook.php > /dev/null 2>/dev/null &');)
Use a job server system such as Gearman.
I'd rate Gearman the coolest, the 'new process and detach' trick is probably the easiest.
Using sleep(10); will block the entire page from loading. What is the correct solution here ?
shot in the dark, try rendering the page first then calling the sleep()? it's difficult to advise a "simple" solution without context on how you are handling the response and what sort of stuff the user needs to see rendered.
You could trigger the Facebook operation via an AJAX call from the client side. You could use a simple setTimeout() to delay the call once the page has loaded:
setTimeout( function(){
// Execute your AJAX call
}, 10000 ); // 1000 miliseconds = 1 second
The page that is being called via AJAX can simply execute the request to Facebook as usual.

Terminate connection to jQuery AJAX request, keep processing php on server side?

I have a signup form that calls a PHP script which can interact with our CRM's API, like so:
CRM API <--> PHP script <--> Signup form
The signup form passes some information to the PHP script in one
AJAX call
The PHP script run a dozen API calls to the CRM to create
an account and attach various data
The CRM returns the new account id it just created to the PHP script
The PHP script passes the account id back to the signup form, at which point the AJAX call is complete and the signup form can continue.
The problem is #2, those dozen calls take about 20 seconds to complete, but the data the signup form needs is generated after the first API call so it could in theory return that data much sooner and do the rest of the stuff server side without holding that AJAX call open the whole time.
I tried flush() and ob_flush() which does output account id to the client before processing is complete, but the jQuery AJAX connection remains open so I'm still stuck waiting for the connection to be closed on the signup form side before anything happens.
So what's the easiest route for returning that account id to the form as fast as possible?
Maybe break out using curl and exec?
if(signing up){
stuff
exec(curl myself, notsignup)
}
else {
bunch of api calls
}
You should probably think about creating a seperate process for the rest of the steps that are needed. One way is that you could after the #1 first api calls has been completed. It responds back to the user, and doesn't try to complete the rest of the 20 calls on the user side.
Then create a queue that will finish the rest. You could always create a table in mysql to store the queue.
Next just create a cronjob that will run in the background, knocking the queue out.
Note: You will not want this cronjob to just start and never stop. Maybe have it run every 5 minutes, but before it starts to run, check to see if another cron is still in progress. If it is then it will check in another 5 minutes to see if it is ok to run.
Hope this helps!
If you only need the information from the first API call to return the form, then I would probably try a different workflow:
Form calls PHP Script
PHP Calls first API Call
PHP Returns to Form
Form processes response
Form calls second PHP Script to complete the process
PHP finishes API Calls (the form can abandon at this point since it sounds like you don't care what happens from here on out).
The workflow requires a little more work and co-ordination for the developer, but presents the most responsive interface to the user.

Using XHR progress events to monitor a MySQL query

I have a php script which is called by a javascript XHR function. In this script it accesses the Facebook API using a token (which is parsed from a Facebook redirect after accepting to connect to facebook).
When I add a progress event to the XHR object, it never runs, and when I log the readystates it gets to, only 2 and 4 are called. I don't think its necessarily a problem with my code, my only guess is that in my PHP script it gets the file contents of 'https://graph.facebook.com/me/albums?limit=0&access_token=' + $token (which json decodes its contents to use as an object which is looped through, adding each of the users' album(s) to a database) doesn't like the fact that I am visiting another url inside this XHR request.
Can anyone give me some guidance so I can make my progress bar 'load'?
Thanks!
The best way to do this is probably to just use good old readyState

Categories