douque9982 2016-02-08 19:49
浏览 81

页面关闭后继续运行PHP脚本[从AJAX启动]

Everything I google tells me this should not be happening, however it is.

I'm building a migration tool to build a 'master database'. I have an admin panel, only accessible to a few select people. There is a merge button that starts an AJAX call to run the migration php function. I'm not positive how long this script takes considering I'm still developing it but none the less I'm expecting a minimum of 20 minutes once pushed to production and populated with the production database. I do NOT need a lecture on best practices telling me not to do it via a GUI. This will become a cron as well, however I want to be able to induce it manually, if the admin desires.

So here's my process. The migration function immediately closes the session session_write_close() allowing me to run multiple php scripts simultaneously. I do this because I start a setInterval that checks to see a session variable. This is my 'progress' which is just an int on what loop iteration I'm on. In my migration script I open sessions, add 1 to that int, and close the sessions again. I do this at the end of each loop.

By doing this I have successfully created a progress for my AJAX. Now I noticed something. If I start my migration, then close out of my tab - or refresh. Once I reload the page my progress continues to grow. This tells me that the migration script is still executing in the background.

If I close 100% out of my browser, or clear my sessions I no longer see progress go up. This however is not because the script stops. This is because my progress indication relies on sessions and once I clear my sessions or close out my browser my session cookie changes. However I know the script is still running because I can query the database manually and see that entries are being added.

NOW to my question: I do NOT want this. If my browser closes, if I press refresh, if I loose connection, etc I want the script to be TERMINATED. I want it to stop mid process.

I tried ignore_user_abort(false); however I'm pretty sure this is specific to command line and made no difference for me.

I want it to be terminated because I'm building a 'progress resume' function where we can choose where to resume the migration progress again.

Any suggestions?

UPDATE:

I didn't want to go this route but some solution I just though of is I could have another session variable. And it's my 'last time client was validated' which could be a timestamp. In my javascript, on the client side, every like 30 seconds I could hit a php script to 'update last time client was validated'. And in my migration function at the beginning of each loop I could check to make sure that timestamp isn't like 60 seconds old for example. If it IS 60 seconds old, or older, I do a die thus stopping my script. This would locally mean 'if there is no client updating this timestamp then we can assume the user closed out of his browser/tab/refreshed'. And as for the function I can ignore this check if in command line (cron). Not the ideal solution but it is my plan B

  • 写回答

1条回答 默认 最新

  • douchengchu8374 2016-02-08 21:02
    关注

    I am, and did, go with the solution to ping from the client to indicate if the client is still alive or not.

    So essentially this is what I did:

    From the client, in javascript, I set up a setInterval to run every 1.5 seconds and that hits a php script via AJAX. This php script updates a session variable with the current timestamp (this could easily be a database value if you needed to, however I didn't want the overhead of another query).

    $_SESSION['migration_listsync_clientLastPing_'.$decodedJson['progressKey']] = time();

    Then, inside my migration function I run a check to see if the 'timestamp' is over 10 seconds old, and if it is I die - thus killing the script.

    if(isset($_SESSION['migration_listsync_clientLastPing_'.$progressKey])){
        $calc = time() - $_SESSION['migration_listsync_clientLastPing_'.$progressKey];
        if($calc > 10){
            die();
        }
    }
    

    I added a 'progressKey' param which is a random number from 1-100 that is generated when the function is called. This number is generated in javascript and passed into both of my AJAX calls. This way if the user refreshes the page and then immediately pressed the button again we won't have 2 instances of the function running. The 'old' instance will die after a few seconds and the new instance will take over.

    This isn't an ideal solution however it is an effective one.

    评论

报告相同问题?

悬赏问题

  • ¥15 关于#网络安全#的问题:求ensp的网络安全,不要步骤要完成版文件
  • ¥15 可否在不同线程中调用封装数据库操作的类
  • ¥20 使用Photon PUN2解决游戏得分同步的问题
  • ¥15 微带串馈天线阵列每个阵元宽度计算
  • ¥15 keil的map文件中Image component sizes各项意思
  • ¥20 求个正点原子stm32f407开发版的贪吃蛇游戏
  • ¥15 划分vlan后,链路不通了?
  • ¥20 求各位懂行的人,注册表能不能看到usb使用得具体信息,干了什么,传输了什么数据
  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 Centos / PETGEM