Add fast AJAX feature, apply to follows
60-80 % speed boost!
This commit is contained in:
parent
db151eea1a
commit
4e7744b67d
@ -1,5 +1,68 @@
|
||||
<?php
|
||||
|
||||
// =============================================================================
|
||||
// FAST AJAX REQUESTS
|
||||
// > Skips any unnecessary theme initialization!
|
||||
// =============================================================================
|
||||
|
||||
define(
|
||||
'FICTIONEER_FAST_AJAX_FUNCTIONS',
|
||||
array(
|
||||
'fictioneer_ajax_get_follows',
|
||||
'fictioneer_ajax_toggle_follow',
|
||||
'fictioneer_ajax_clear_my_follows',
|
||||
'fictioneer_ajax_mark_follows_read',
|
||||
'fictioneer_ajax_get_follows_notifications',
|
||||
'fictioneer_ajax_get_follows_list'
|
||||
)
|
||||
);
|
||||
|
||||
if (
|
||||
isset( $_REQUEST['fcn_fast_ajax'] ) &&
|
||||
isset( $_REQUEST['action'] ) &&
|
||||
! ( defined('REST_REQUEST') && REST_REQUEST )
|
||||
) {
|
||||
fictioneer_do_fast_ajax();
|
||||
}
|
||||
|
||||
function fictioneer_do_fast_ajax() {
|
||||
$action = $_REQUEST['action'];
|
||||
|
||||
// Allowed action?
|
||||
if (
|
||||
! defined('FICTIONEER_FAST_AJAX_FUNCTIONS') ||
|
||||
! in_array( $action, FICTIONEER_FAST_AJAX_FUNCTIONS, true ) ||
|
||||
strpos( $action, 'fictioneer_ajax' ) !== 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Include required files
|
||||
require_once __DIR__ . '/includes/functions/_utility.php';
|
||||
require_once __DIR__ . '/includes/functions/_query_helpers.php';
|
||||
|
||||
if ( get_option( 'fictioneer_enable_follows' ) && strpos( $action, '_follow' ) !== false ) {
|
||||
require_once __DIR__ . '/includes/functions/_content_helpers.php';
|
||||
require_once __DIR__ . '/includes/functions/users/_follows.php';
|
||||
}
|
||||
|
||||
// Function exists?
|
||||
if ( ! function_exists( $action ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set DOING_AJAX true
|
||||
if ( ! defined( 'DOING_AJAX' ) ) {
|
||||
define( 'DOING_AJAX', true );
|
||||
}
|
||||
|
||||
// Call function
|
||||
call_user_func( $action );
|
||||
|
||||
// Terminate in case something goes wrong
|
||||
die();
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// CONSTANTS/SETTINGS
|
||||
// =============================================================================
|
||||
|
@ -78,7 +78,9 @@ function fictioneer_ajax_get_follows() {
|
||||
wp_date( 'c', $user_follows['seen'] / 1000 )
|
||||
);
|
||||
|
||||
if ( $latest ) $new = count( $latest );
|
||||
if ( $latest ) {
|
||||
$new = count( $latest );
|
||||
}
|
||||
}
|
||||
|
||||
$user_follows['new'] = $new;
|
||||
|
2
js/follows.min.js
vendored
2
js/follows.min.js
vendored
@ -1 +1 @@
|
||||
const fcn_desktopFollowList=_$$$("follow-menu-scroll"),fcn_mobileFollowList=_$$$("mobile-menu-follows-list"),fcn_followsMenuItem=_$$$("follow-menu-button");var fcn_userFollowsTimeout,fcn_follows;function fcn_initializeFollows(){fcn_follows=fcn_getFollows(),fcn_fetchFollowsFromDatabase()}function fcn_getFollows(){const o=localStorage.getItem("fcnStoryFollows");return o&&fcn_isValidJSONString(o)?JSON.parse(o):{lastLoaded:0,data:{},seen:Date.now(),new:!1}}function fcn_fetchFollowsFromDatabase(){fcn_ajaxLimitThreshold<fcn_follows.lastLoaded?fcn_updateFollowsView():fcn_ajaxGet({action:"fictioneer_ajax_get_follows"}).then((o=>{if(o.success){let t=o.data.follows;t=fcn_isValidJSONString(t)?t:"{}",t=JSON.parse(t),(fcn_follows="object"==typeof t&&t.data&&Object.keys(t.data).length>0?t:{data:{},seen:Date.now(),new:!1}).lastLoaded=Date.now()}})).catch((()=>{localStorage.removeItem("fcnStoryFollows"),fcn_follows=!1})).then((()=>{fcn_updateFollowsView(),localStorage.removeItem("fcnBookshelfContent")}))}function fcn_updateFollowsView(){if(!fcn_follows)return;_$$(".button-follow-story").forEach((o=>{o.classList.toggle("_followed",fcn_follows?.data.hasOwnProperty(o.dataset.storyId))})),_$$(".card").forEach((o=>{o.classList.toggle("has-follow",fcn_follows?.data.hasOwnProperty(o.dataset.storyId))})),localStorage.setItem("fcnStoryFollows",JSON.stringify(fcn_follows));const o=parseInt(fcn_follows.new)>0;_$$(".mark-follows-read, .follows-alert-number, .mobile-menu-button").forEach((t=>{t.classList.toggle("_new",o),o>0&&(t.dataset.newCount=fcn_follows.new)}))}function fcn_toggleFollow(o){const t=fcn_getFollows();if(localStorage.removeItem("fcnBookshelfContent"),JSON.stringify(fcn_follows.data[o])!==JSON.stringify(t.data[o]))return fcn_follows=t,fcn_showNotification(__("Follows re-synchronized.","fictioneer")),void fcn_updateFollowsView();(fcn_follows=t).data.hasOwnProperty(o)?delete fcn_follows.data[o]:fcn_follows.data[o]={timestamp:Date.now()},fcn_follows.lastLoaded=0,fcn_updateFollowsView(),clearTimeout(fcn_userFollowsTimeout),fcn_userFollowsTimeout=setTimeout((()=>{fcn_ajaxPost({action:"fictioneer_ajax_toggle_follow",story_id:o,set:fcn_follows.data.hasOwnProperty(o)}).then((o=>{o.data.error&&fcn_showNotification(o.data.error,5,"warning")})).catch((o=>{o.status&&o.statusText&&fcn_showNotification(`${o.status}: ${o.statusText}`,5,"warning")}))}),fictioneer_ajax.post_debounce_rate)}function fcn_setupFollowsHTML(){fcn_followsMenuItem.classList.contains("_loaded")||fcn_ajaxGet({action:"fictioneer_ajax_get_follows_notifications"}).then((o=>{o.data.html&&(fcn_desktopFollowList.innerHTML=o.data.html,fcn_mobileFollowList.innerHTML=o.data.html)})).catch((o=>{o.status&&o.statusText&&fcn_showNotification(`${o.status}: ${o.statusText}`,5,"warning"),fcn_desktopFollowList.remove(),fcn_mobileFollowList.remove()})).then((()=>{fcn_followsMenuItem.classList.add("_loaded")}))}function fcn_markFollowsRead(){fcn_followsMenuItem.classList.contains("_new")&&fcn_followsMenuItem.classList.contains("_loaded")&&(_$$(".mark-follows-read, .follows-alert-number, .follow-item, .mobile-menu-button").forEach((o=>{o.classList.remove("_new")})),fcn_follows.new=0,fcn_follows.lastLoaded=0,localStorage.setItem("fcnStoryFollows",JSON.stringify(fcn_follows)),fcn_ajaxPost({action:"fictioneer_ajax_mark_follows_read"}).catch((o=>{o.status&&o.statusText&&fcn_showNotification(`${o.status}: ${o.statusText}`,5,"warning")})))}fcn_isLoggedIn&&fcn_initializeFollows(),fcn_followsMenuItem?.addEventListener("mouseover",(()=>{fcn_setupFollowsHTML()}),{once:!0}),fcn_followsMenuItem?.addEventListener("focus",(()=>{fcn_setupFollowsHTML()}),{once:!0}),_$('.mobile-menu__frame-button[data-frame-target="follows"]')?.addEventListener("click",(()=>{fcn_setupFollowsHTML()}),{once:!0}),_$$(".button-follow-story").forEach((o=>{o.addEventListener("click",(o=>{fcn_toggleFollow(o.currentTarget.dataset.storyId)}))})),_$$(".mark-follows-read").forEach((o=>{o.addEventListener("click",(()=>{fcn_markFollowsRead()}))}));
|
||||
const fcn_desktopFollowList=_$$$("follow-menu-scroll"),fcn_mobileFollowList=_$$$("mobile-menu-follows-list"),fcn_followsMenuItem=_$$$("follow-menu-button");var fcn_userFollowsTimeout,fcn_follows;function fcn_initializeFollows(){fcn_follows=fcn_getFollows(),fcn_fetchFollowsFromDatabase()}function fcn_getFollows(){const o=localStorage.getItem("fcnStoryFollows");return o&&fcn_isValidJSONString(o)?JSON.parse(o):{lastLoaded:0,data:{},seen:Date.now(),new:!1}}function fcn_fetchFollowsFromDatabase(){fcn_ajaxLimitThreshold<fcn_follows.lastLoaded?fcn_updateFollowsView():fcn_ajaxGet({action:"fictioneer_ajax_get_follows",fcn_fast_ajax:1}).then((o=>{if(o.success){let t=o.data.follows;t=fcn_isValidJSONString(t)?t:"{}",t=JSON.parse(t),(fcn_follows="object"==typeof t&&t.data&&Object.keys(t.data).length>0?t:{data:{},seen:Date.now(),new:!1}).lastLoaded=Date.now()}})).catch((()=>{localStorage.removeItem("fcnStoryFollows"),fcn_follows=!1})).then((()=>{fcn_updateFollowsView(),localStorage.removeItem("fcnBookshelfContent")}))}function fcn_updateFollowsView(){if(!fcn_follows)return;_$$(".button-follow-story").forEach((o=>{o.classList.toggle("_followed",fcn_follows?.data.hasOwnProperty(o.dataset.storyId))})),_$$(".card").forEach((o=>{o.classList.toggle("has-follow",fcn_follows?.data.hasOwnProperty(o.dataset.storyId))})),localStorage.setItem("fcnStoryFollows",JSON.stringify(fcn_follows));const o=parseInt(fcn_follows.new)>0;_$$(".mark-follows-read, .follows-alert-number, .mobile-menu-button").forEach((t=>{t.classList.toggle("_new",o),o>0&&(t.dataset.newCount=fcn_follows.new)}))}function fcn_toggleFollow(o){const t=fcn_getFollows();if(localStorage.removeItem("fcnBookshelfContent"),JSON.stringify(fcn_follows.data[o])!==JSON.stringify(t.data[o]))return fcn_follows=t,fcn_showNotification(__("Follows re-synchronized.","fictioneer")),void fcn_updateFollowsView();(fcn_follows=t).data.hasOwnProperty(o)?delete fcn_follows.data[o]:fcn_follows.data[o]={timestamp:Date.now()},fcn_follows.lastLoaded=0,fcn_updateFollowsView(),clearTimeout(fcn_userFollowsTimeout),fcn_userFollowsTimeout=setTimeout((()=>{fcn_ajaxPost({action:"fictioneer_ajax_toggle_follow",fcn_fast_ajax:1,story_id:o,set:fcn_follows.data.hasOwnProperty(o)}).then((o=>{o.data.error&&fcn_showNotification(o.data.error,5,"warning")})).catch((o=>{o.status&&o.statusText&&fcn_showNotification(`${o.status}: ${o.statusText}`,5,"warning")}))}),fictioneer_ajax.post_debounce_rate)}function fcn_setupFollowsHTML(){fcn_followsMenuItem.classList.contains("_loaded")||fcn_ajaxGet({action:"fictioneer_ajax_get_follows_notifications",fcn_fast_ajax:1}).then((o=>{o.data.html&&(fcn_desktopFollowList.innerHTML=o.data.html,fcn_mobileFollowList.innerHTML=o.data.html)})).catch((o=>{o.status&&o.statusText&&fcn_showNotification(`${o.status}: ${o.statusText}`,5,"warning"),fcn_desktopFollowList.remove(),fcn_mobileFollowList.remove()})).then((()=>{fcn_followsMenuItem.classList.add("_loaded")}))}function fcn_markFollowsRead(){fcn_followsMenuItem.classList.contains("_new")&&fcn_followsMenuItem.classList.contains("_loaded")&&(_$$(".mark-follows-read, .follows-alert-number, .follow-item, .mobile-menu-button").forEach((o=>{o.classList.remove("_new")})),fcn_follows.new=0,fcn_follows.lastLoaded=0,localStorage.setItem("fcnStoryFollows",JSON.stringify(fcn_follows)),fcn_ajaxPost({action:"fictioneer_ajax_mark_follows_read",fcn_fast_ajax:1}).catch((o=>{o.status&&o.statusText&&fcn_showNotification(`${o.status}: ${o.statusText}`,5,"warning")})))}fcn_isLoggedIn&&fcn_initializeFollows(),fcn_followsMenuItem?.addEventListener("mouseover",(()=>{fcn_setupFollowsHTML()}),{once:!0}),fcn_followsMenuItem?.addEventListener("focus",(()=>{fcn_setupFollowsHTML()}),{once:!0}),_$('.mobile-menu__frame-button[data-frame-target="follows"]')?.addEventListener("click",(()=>{fcn_setupFollowsHTML()}),{once:!0}),_$$(".button-follow-story").forEach((o=>{o.addEventListener("click",(o=>{fcn_toggleFollow(o.currentTarget.dataset.storyId)}))})),_$$(".mark-follows-read").forEach((o=>{o.addEventListener("click",(()=>{fcn_markFollowsRead()}))}));
|
42
mu-plugins/fictioneer_fast_ajax.php
Normal file
42
mu-plugins/fictioneer_fast_ajax.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: Fictioneer Fast AJAX
|
||||
* Description: Skips plugins and theme initialization for faster requests.
|
||||
* Version: 1.0
|
||||
* Author: Tetrakern
|
||||
* Author URI: https://github.com/Tetrakern
|
||||
* Donate link: https://ko-fi.com/tetrakern
|
||||
* License: GNU General Public License v3.0 or later
|
||||
* License URI: http://www.gnu.org/licenses/gpl.html
|
||||
*/
|
||||
|
||||
// Check if fast AJAX is activated
|
||||
if ( ! isset( $_REQUEST['fcn_fast_ajax'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if action is set and allowed
|
||||
if (
|
||||
! isset( $_REQUEST['action'] ) ||
|
||||
strpos( $_REQUEST['action'], 'fictioneer_ajax' ) !== 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
function fictioneer_exclude_plugins( $plugins ) {
|
||||
// Setup
|
||||
$allow_list = array(
|
||||
'fictioneer-email-subscriptions/fictioneer-email-subscriptions.php'
|
||||
);
|
||||
|
||||
// Remove not allowed plugins
|
||||
foreach ( $plugins as $index => $plugin ) {
|
||||
if ( ! in_array( $plugin, $allow_list ) ) {
|
||||
unset( $plugins[ $index ] );
|
||||
}
|
||||
}
|
||||
|
||||
// Continue filter
|
||||
return $plugins;
|
||||
}
|
||||
add_filter( 'option_active_plugins', 'fictioneer_exclude_plugins' );
|
@ -66,7 +66,8 @@ function fcn_fetchFollowsFromDatabase() {
|
||||
|
||||
// Request
|
||||
fcn_ajaxGet({
|
||||
'action': 'fictioneer_ajax_get_follows'
|
||||
'action': 'fictioneer_ajax_get_follows',
|
||||
'fcn_fast_ajax': 1
|
||||
})
|
||||
.then((response) => {
|
||||
// Check for success
|
||||
@ -198,6 +199,7 @@ function fcn_toggleFollow(storyId) {
|
||||
fcn_userFollowsTimeout = setTimeout(() => {
|
||||
fcn_ajaxPost({
|
||||
'action': 'fictioneer_ajax_toggle_follow',
|
||||
'fcn_fast_ajax': 1,
|
||||
'story_id': storyId,
|
||||
'set': fcn_follows.data.hasOwnProperty(storyId)
|
||||
})
|
||||
@ -231,7 +233,8 @@ function fcn_setupFollowsHTML() {
|
||||
|
||||
// Request
|
||||
fcn_ajaxGet({
|
||||
'action': 'fictioneer_ajax_get_follows_notifications'
|
||||
'action': 'fictioneer_ajax_get_follows_notifications',
|
||||
'fcn_fast_ajax': 1
|
||||
})
|
||||
.then((response) => {
|
||||
// Any Follows HTML retrieved?
|
||||
@ -285,7 +288,8 @@ function fcn_markFollowsRead() {
|
||||
|
||||
// Request
|
||||
fcn_ajaxPost({
|
||||
'action': 'fictioneer_ajax_mark_follows_read'
|
||||
'action': 'fictioneer_ajax_mark_follows_read',
|
||||
'fcn_fast_ajax': 1
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.status && error.statusText) {
|
||||
|
@ -822,3 +822,45 @@ function fcn_html(...args) {
|
||||
template.innerHTML = String.raw(...args).trim();
|
||||
return template.content.firstChild;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// DEV: AJAX BENCHMARK
|
||||
// =============================================================================
|
||||
|
||||
// /**
|
||||
// * Benchmark AJAX request response times
|
||||
// *
|
||||
// * Default: benchmarkAjax(20, {'action': '...'});
|
||||
// *
|
||||
// * Fast: benchmarkAjax(20, {'fcn_fast_ajax': 1, 'action': '...'});
|
||||
// *
|
||||
// * @param {number} n - The number of times the AJAX request should be made.
|
||||
// * @param {Object} data - The payload for the AJAX request.
|
||||
// * @param {String} url - Optional. The AJAX URL if different from the default.
|
||||
// * @param {Object} headers - Optional. Headers for the request.
|
||||
// * @returns {Promise<number>} Promise that resolves with the average response time in milliseconds.
|
||||
// */
|
||||
|
||||
// async function benchmarkAjax(n = 1, data = {}, url = null, headers = {}) {
|
||||
// let totalTime = 0;
|
||||
|
||||
// console.log(`Starting benchmark with ${n} AJAX requests...`);
|
||||
|
||||
// for (let i = 0; i < n; i++) {
|
||||
// const startTime = performance.now();
|
||||
|
||||
// try {
|
||||
// await fcn_ajaxGet(data, url, headers);
|
||||
// const endTime = performance.now();
|
||||
// totalTime += (endTime - startTime);
|
||||
// } catch (error) {
|
||||
// console.error('Error during AJAX request:', error);
|
||||
// }
|
||||
// }
|
||||
|
||||
// const averageTime = totalTime / n;
|
||||
|
||||
// console.log(`Finished benchmarking. Average AJAX response time over ${n} requests: ${averageTime.toFixed(2)} ms`);
|
||||
|
||||
// return averageTime;
|
||||
// }
|
||||
|
Loading…
x
Reference in New Issue
Block a user