You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何延迟WordPress函数2秒执行或优化热销徽章功能?

问题分析与解决方案

你的函数崩溃核心原因不是执行时机,而是实时查询+遍历所有关联订单的性能爆炸——每个产品归档页的商品都会触发一次全量订单查询,再逐个加载订单、遍历订单项求和,数据库和PHP资源直接被耗尽。Argos的延迟显示是前端优化,但其后台肯定提前做了数据预计算,而非实时查询。

一、最优解决方案:预计算销量+前端异步加载(完全对标Argos)

1. 后台预计算周销量(彻底解决性能问题)

通过订单完成钩子和定时任务,提前把每个产品的周销量存在产品元数据里,避免实时查询:

// 订单完成时,累加对应产品的周销量
add_action('woocommerce_order_status_completed', 'update_product_weekly_sales', 10, 1);
function update_product_weekly_sales($order_id) {
    $order = wc_get_order($order_id);
    $week_start = date('Y-m-d', strtotime('last Monday')); // 以周一为周起始
    $meta_key = 'weekly_sales_' . $week_start;

    foreach ($order->get_items() as $item) {
        $product_id = $item->get_product_id();
        $qty = $item->get_quantity();
        // 累加销量到对应周的元字段
        $current_sales = get_post_meta($product_id, $meta_key, true);
        update_post_meta($product_id, $meta_key, absint($current_sales) + $qty);
    }
}

// 每周一凌晨自动清理两周前的旧销量数据(避免元数据冗余)
add_action('wp_weekly_sales_cleanup', 'cleanup_old_weekly_sales');
function cleanup_old_weekly_sales() {
    $two_weeks_ago = date('Y-m-d', strtotime('-2 weeks last Monday'));
    global $wpdb;
    $wpdb->query($wpdb->prepare(
        "DELETE FROM $wpdb->postmeta WHERE meta_key = %s",
        'weekly_sales_' . $two_weeks_ago
    ));
}

// 注册定时任务
add_action('wp', function() {
    if (!wp_next_scheduled('wp_weekly_sales_cleanup')) {
        wp_schedule_event(strtotime('next Monday 00:00:00'), 'weekly', 'wp_weekly_sales_cleanup');
    }
});

2. 前端异步加载徽章(实现页面加载后显示)

不在PHP循环里直接输出徽章,先渲染占位容器,等页面加载完成后批量请求数据:

第一步:PHP渲染占位容器

add_action('woocommerce_before_shop_loop_item_title', 'add_trending_badge_placeholder', 11);
function add_trending_badge_placeholder() {
    global $product;
    echo '<div class="trending-block-loop" data-product-id="' . $product->get_ID() . '"></div>';
}

第二步:JS批量请求并显示徽章

把这段代码存为主题目录下的js/trending-badge.js:

document.addEventListener('DOMContentLoaded', function() {
    const badgeContainers = document.querySelectorAll('.trending-block-loop');
    const productIds = Array.from(badgeContainers).map(container => container.dataset.productId);

    if (!productIds.length) return;

    // 批量请求销量数据
    fetch('/wp-admin/admin-ajax.php', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'X-WP-Nonce': wpApiSettings.nonce
        },
        body: `action=get_product_weekly_sales&product_ids=${productIds.join(',')}`
    })
    .then(res => res.json())
    .then(salesData => {
        badgeContainers.forEach(container => {
            const productId = container.dataset.productId;
            if (salesData[productId] && salesData[productId] > 20) {
                container.innerHTML = `<svg width="16" height="16" viewBox="0 0 24 24"><path d="M8.625 0c.61 7.189-5.625 9.664-5.625 15.996 0 4.301 3.069 7.972 9 8.004 5.931.032 9-4.414 9-8.956 0-4.141-2.062-8.046-5.952-10.474.924 2.607-.306 4.988-1.501 5.808.07-3.337-1.125-8.289-4.922-10.378zm4.711 13c3.755 3.989 1.449 9-1.567 9-1.835 0-2.779-1.265-2.769-2.577.019-2.433 2.737-2.435 4.336-6.423z"/></svg> Selling Fast`;
            } else {
                container.style.display = 'none';
            }
        });
    });
});

第三步:注册AJAX接口并本地化JS

在主题functions.php中添加:

add_action('wp_enqueue_scripts', 'enqueue_trending_badge_script');
function enqueue_trending_badge_script() {
    wp_enqueue_script('trending-badge', get_template_directory_uri() . '/js/trending-badge.js', [], '1.0', true);
    // 传递WP安全验证nonce
    wp_localize_script('trending-badge', 'wpApiSettings', [
        'nonce' => wp_create_nonce('wp_rest')
    ]);
}

// AJAX处理函数:返回批量产品的周销量
add_action('wp_ajax_get_product_weekly_sales', 'get_product_weekly_sales');
add_action('wp_ajax_nopriv_get_product_weekly_sales', 'get_product_weekly_sales');
function get_product_weekly_sales() {
    check_ajax_referer('wp_rest');
    $product_ids = explode(',', $_POST['product_ids']);
    $week_start = date('Y-m-d', strtotime('last Monday'));
    $meta_key = 'weekly_sales_' . $week_start;
    $sales_data = [];

    foreach ($product_ids as $id) {
        $sales_data[$id] = absint(get_post_meta($id, $meta_key, true));
    }

    wp_send_json($sales_data);
    wp_die();
}

二、临时治标方案:仅延迟前端执行(不解决后台性能问题)

如果不想改动后端逻辑,仅做前端延迟显示(但后台查询压力依然存在,不推荐):

add_action('woocommerce_before_shop_loop_item_title', 'delayed_trending_badge', 11);
function delayed_trending_badge() {
    global $product;
    $product_id = $product->get_ID();
    echo '<div class="trending-container" data-product-id="' . $product_id . '"></div>';
    echo '<script>
        setTimeout(() => {
            fetch("/wp-admin/admin-ajax.php", {
                method: "POST",
                headers: {
                    "Content-Type": "application/x-www-form-urlencoded",
                    "X-WP-Nonce": wpApiSettings.nonce
                },
                body: `action=check_trending&product_id=' . $product_id . '`
            })
            .then(res => res.text())
            .then(html => {
                document.querySelector("[data-product-id=' . $product_id . ']").innerHTML = html;
            });
        }, 2000);
    </script>';
}

// AJAX处理函数(复用原查询逻辑,性能差)
add_action('wp_ajax_check_trending', 'check_trending');
add_action('wp_ajax_nopriv_check_trending', 'check_trending');
function check_trending() {
    $product_id = $_POST['product_id'];
    $all_orders = wc_get_orders([
        'limit' => -1,
        'status' => array_map('wc_get_order_status_name', wc_get_is_paid_statuses()),
        'date_after' => date('Y-m-d', strtotime('-1 week')),
        'return' => 'ids',
        'meta_query' => [['key' => '_product_id', 'value' => $product_id]]
    ]);
    $count = 0;
    foreach ($all_orders as $order_id) {
        $order = wc_get_order($order_id);
        foreach ($order->get_items() as $item) {
            if ($item->get_product_id() == $product_id) {
                $count += absint($item['qty']);
            }
        }
    }
    if ($count > 20) {
        echo "<div class='trending-block-loop'><svg width='16' height='16' viewBox='0 0 24 24'><path d='M8.625 0c.61 7.189-5.625 9.664-5.625 15.996 0 4.301 3.069 7.972 9 8.004 5.931.032 9-4.414 9-8.956 0-4.141-2.062-8.046-5.952-10.474.924 2.607-.306 4.988-1.501 5.808.07-3.337-1.125-8.289-4.922-10.378zm4.711 13c3.755 3.989 1.449 9-1.567 9-1.835 0-2.779-1.265-2.769-2.577.019-2.433 2.737-2.435 4.336-6.423z'/></svg> Selling Fast</div>";
    }
    wp_die();
}

内容的提问来源于stack exchange,提问作者FoamyMedia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 10:22:05