0

I have a site where users can publish links. Users fill a form with 2 fields:

  • Title
  • URL

When the user clicks "submit" I have a crawler that looks for an image of the link provided and makes a thumbnail.

The problem is that the crawler usually takes about 5-10 seconds to finish loading and cropping the thumb.

I thought I could do an ajax call like this. As you can see, when the user submits a link first we see if its valid (first ajax call) then if succesful we do another ajax call to try to find and save the image of this link.

My idea was to do that while I move the user to the links.php page, however, I find that if I do it like this the AJAX call breaks and the function in save_image.php doesn't run.

What can I do to avoid making my users wait for the save_image.php process? I need this process to run, but I don't need any data returned.

$.ajax({
                    url: 'publish/submit_link.php',
                    type: 'POST',
                    dataType: 'JSON',
                    data: {
                        link            : link,
                        title           : title,
                    },
                    success: function (data) {
                        if (data) 
                        {
                            $.ajax({
                                url: 'publish/save_image.php',                                      type: 'POST',
                                data: {
                                        id              : data.id,
                                        type            : data.type,
                                    url             : url,
                                        csrf_test_name  : csrf
                                }
                            });
                        }

                        //THIS NEXT LINE BREAKS SECOND AJAX CALL
                        window.location = 'links.php';

                    }   
});

Thanks in advance!

SUMMING UP: I want the user to submit a link and redirect the user to the links page while the thumbnail for that link is being generated. I don't want to show the thumbnail to the user.

John Shepard
  • 937
  • 1
  • 9
  • 27
  • 1
    Let me get this straight... You want the user to submit a link, then generate a thumbnail, then **show it to the user**. Is that correct? So you expect the link (and thumbnail) to be there by the time the user loads `links.php`? – Peter-Paul van Gemerden Aug 18 '12 at 11:51
  • I want the user to submit a link and redirect the user to the links page while the thumbnail is being generated. I don't want to show the thumbnail to the user. – John Shepard Aug 18 '12 at 11:53

4 Answers4

3

The AJAX request seems to fail, because when you navigate away, the user request is aborted. Because of that, the execution of save_image.php is interrupted.

You can use PHP's ignore_user_abort to force the PHP process to continue in the background. Put it at the top of save_image.php:

<?php
    ignore_user_abort(true);

    // ... save image, etc.
?>

For this to work, you have to send (and flush) some output to the client:

PHP will not detect that the user has aborted the connection until an attempt is made to send information to the client. Simply using an echo statement does not guarantee that information is sent, see flush().

Any output should work (e.g. "OK"). This might be a bit of a challenge considering you're using a framework, but it shouldn't be impossible. This might work: Flushing with CodeIgniter

You can read more about PHP connection handling here.

  • I have tried but it is not working :( chrome console says "name = save_image.php, type = POST, status = cancelled" – John Shepard Aug 18 '12 at 12:12
  • @JohnShepard: Sorry, my bad. You should pass `true` to `ignore_user_abort`, otherwise it will return the previous setting. – Peter-Paul van Gemerden Aug 18 '12 at 12:15
  • I am using codeigniter, and I put ignore_user_abort at the top of the function in the controller – John Shepard Aug 18 '12 at 12:15
  • Still not working with ignore_user_abort(true); are you familiar with MVCs? Could it be the framework? – John Shepard Aug 18 '12 at 12:17
  • @JohnShepard: it seems there is another hurdle; see my latest edit. – Peter-Paul van Gemerden Aug 18 '12 at 12:26
  • I tried the "flushing with codeigniter" link but no luck so far. As you can see there, someone with the same CodeIgniter version (v2.1) posted a last thread saying that with the new CI none of the previous lines worked. I tried anyway. But didn't get it to work! – John Shepard Aug 18 '12 at 16:10
  • @JohnShepard: It seems this is non-trivial with CI2. If I were you, I'd start looking into running a background process of some sort. Some possibilities: a shell script and [`exec`](http://www.php.net/manual/en/function.exec.php), a chron script, or a background daemon. How to do this depends heavily on your hosting environment. – Peter-Paul van Gemerden Aug 18 '12 at 17:11
  • Me and my partner have decided just 15 min ago to go for a chron script that runs every 10 mins. Thanks for your help PPvG, here is my upvote! People like you are the pilars of stackoverflow, keep up the good work :) – John Shepard Aug 18 '12 at 18:00
  • Works great for my cause. I have messages to mark as read and redirect at the same time. Thanks. Upvoting. – Gogol Oct 15 '15 at 14:06
1

force user to fill first the url and then the title, when user go to title field start crawl data, till finish the title and press sumbit you will gain some time and make the proccess apparently faster.

Sotiris
  • 38,986
  • 11
  • 53
  • 85
0

Why use XHR at all if you don't need the data returned? Just let your form submit the link to links.php and let it save the image there!

Some Guy
  • 15,854
  • 10
  • 58
  • 67
  • If i do that, php would run the whole process and THEN redirect the user. I need to redirect the user WHILE the process save_image.php is running – John Shepard Aug 18 '12 at 11:46
  • Where does `links.php` redirect you too? I think you can simply have the image be saved by the server (asynchronously if it takes a lot of time) while the user is shown whatever he needs to see. Have a look at [this question](http://stackoverflow.com/questions/222414/asynchronous-shell-exec-in-php) – Some Guy Aug 18 '12 at 11:49
  • links.php just shows all the links the user has submitted. It doesn't redirect the user anywhere. – John Shepard Aug 18 '12 at 11:50
  • Ah. Just understood what you meant by the comment on the question. – Some Guy Aug 18 '12 at 11:56
  • Well, the problem here is that you're sending the XHR request when the user *submits*. That doesn't give you any time advantage. I think you should add an `onblur` event to the image's input field, and send out the XHR request right away. Then the thumbnail can be generated while the user is still filling the form. To reduce the load, you could check `onblur` if the value of the field is indeed a URL. – Some Guy Aug 18 '12 at 12:02
  • Try PPvG's solution. Looks promising. – Some Guy Aug 18 '12 at 12:03
0

to understand your problem, we need to understand the working of javascript

your code is as follows

$.ajax({
                    url: 'publish/submit_link.php',
                    type: 'POST',
                    dataType: 'JSON',
                    data: {
                        link            : link,
                        title           : title,
                    },
                    success: function (data) {
                        if (data) 
                        {
                            $.ajax({
                                url: 'publish/save_image.php',                                      type: 'POST',
                                data: {
                                        id              : data.id,
                                        type            : data.type,
                                    url             : url,
                                        csrf_test_name  : csrf
                                }
                            });
                        }

                        //THIS NEXT LINE BREAKS SECOND AJAX CALL
                        window.location = 'links.php';

                    }   
});

from the above i can say that as soon as ajax request is made, java script executes the second line regardless of the response.

we can take the following example

$.ajax({
                    url: 'publish/submit_link.php',
                    type: 'POST',
                    dataType: 'JSON',
                    data: {
                        link            : link,
                        title           : title,
                    },
                    success: function (data) 
                    {
                         console.log(data);
                    }
});

for(var i = 0; i < 15000000; i++)
{
      console.log(i);
}

you may see the output as follows

1
2
3
.
.
.
1000
data//response of ajax
.
.
14999999

so to avoid that you can use either jQuery.when() our ajax success function.

Hopefully this will help you

KuKu
  • 646
  • 2
  • 15
  • 38
  • notice that I want the user to submit a link and redirect the user to the links page while the thumbnail for that link is being generated. This means that I don't want to wait for the second Ajax call to return anything. I don't need to know when it has finished. – John Shepard Aug 20 '12 at 07:08
  • yes.. but this is the way ajax works.. i know that you do not need that response for redirecting but if you wants to complete the second request you need to put the redirect code either in success function or `$.when().then()` will also work. – KuKu Aug 20 '12 at 08:46