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

PHP多线程Curl调用社交平台API后,通过WordPress admin_ajax返回JSON至前端JS的问题排查

Fixing "Unexpected token A in JSON at position 0" & Escaped Backslashes in WordPress admin_ajax Response

Let's break down what's causing your issues and how to fix them step by step:

The Root Cause

Your multi_thread_curl function fetches raw JSON strings from the Facebook/Instagram APIs, then you run json_encode($results) on that array of pre-encoded JSON. This leads to double JSON encoding—the original JSON gets escaped (hence the backslashes), and when your frontend tries to parse it, it ends up with invalid JSON that throws the "Unexpected token" error.

Additionally, your frontend Fetch call references an undefined headers variable, which might be causing unintended request behavior.

Step 1: Fix the PHP Double Encoding Issue

Modify your sns_display_post_action function to decode each API response before encoding the final result. This ensures you only encode the data once, producing clean, unescaped JSON:

function sns_display_post_action(){
    $facebookID = get_option( 'facebook_page_id' );
    $instagramID = get_option( 'instagram_profile_id' );
    $instagramName = get_option('instagram_profile_name');
    $optionArray = array(
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_TIMEOUT => 10
    );
    $access_token = get_option('access_token');
    $limitpost = get_option( 'post_count_number' );
    $data1 = "https://graph.facebook.com/v14.0/$instagramID?fields=business_discovery.username($instagramName){id,name,profile_picture_url,media.limit($limitpost){id,owner,username,media_type,permalink,caption,timestamp,media_url,children{media_url}}}&access_token=$access_token";
    $data2 = "https://graph.facebook.com/v14.0/$facebookID?fields=id,about,name,picture{url},posts.limit($limitpost){id,created_time,message,permalink_url,attachments{media_type,type,media,url,subattachments,unshimmed_url,description},full_picture}&access_token=$access_token";
    $urlArray = array(
        $data1,
        $data2
    );
    $nThreads = 2;
    $results = multi_thread_curl($urlArray, $optionArray, $nThreads);

    // Decode raw API JSON responses to PHP arrays
    $parsed_results = [];
    foreach ($results as $key => $raw_json) {
        $parsed = json_decode($raw_json, true); // true = return associative array
        if ($parsed !== null) {
            $parsed_results[$key] = $parsed;
        } else {
            // Optional: Handle invalid JSON from API
            $parsed_results[$key] = ['error' => 'Failed to parse API response'];
        }
    }

    // Send proper JSON header to avoid MIME type conflicts
    header('Content-Type: application/json');
    echo json_encode($parsed_results);
    exit();
}
add_action( 'wp_ajax_sns_post_action', 'sns_display_post_action');
add_action( 'wp_ajax_nopriv_sns_post_action', 'sns_display_post_action');

Why This Works:

  • We convert each raw JSON string from the API into a PHP array with json_decode, so the final json_encode only processes native PHP data structures.
  • The Content-Type header ensures WordPress sends the response with the correct MIME type, which helps the Fetch API interpret it properly.

Step 2: Fix the Frontend Fetch Call

Your current code uses an undefined headers variable. When using FormData, the browser automatically sets the correct Content-Type header (with the boundary), so we can clean this up and add basic error handling:

let params = new FormData();
params.append("action", sns_show_options.action);
params.append("nonce", sns_show_options.nonce);

fetch(sns_show_options.api, {
    method: 'POST', // admin_ajax requires POST requests
    body: params
})
.then(response => {
    // Catch HTTP errors before parsing JSON
    if (!response.ok) {
        throw new Error(`Request failed! Status: ${response.status}`);
    }
    return response.json();
})
.then(res => {
    console.log(res);
})
.catch(error => {
    console.error('Fetch error:', error);
});

Key Fixes Here:

  • Explicitly set method: 'POST' since WordPress admin_ajax requires POST for action requests.
  • Removed the undefined headers property—FormData handles this automatically.
  • Added error handling to catch HTTP issues or parsing failures, making debugging easier.

Step 3: Clean Up the multi_thread_curl Function (Optional)

Your current function leaves curl handles open (you commented out curl_multi_remove_handle), which can lead to resource leaks. Let's fix that:

function multi_thread_curl($urlArray, $optionArray, $nThreads) {
    $curlArray = array_chunk($urlArray, $nThreads, true);
    $results = [];
    $ch_prefix = 'ch_';

    foreach($curlArray as $threads) {
        $mh = curl_multi_init();
        $handles = [];

        foreach($threads as $thread=>$value) {
            $handle_name = $ch_prefix . $thread;
            $$handle_name = curl_init();
            curl_setopt_array($$handle_name, $optionArray);
            curl_setopt($$handle_name, CURLOPT_URL, $value);
            $handles[$thread] = $$handle_name;
            curl_multi_add_handle($mh, $$handle_name);
        }

        $active = null;
        do {
            $mrc = curl_multi_exec($mh, $active);
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);

        while ($active && $mrc == CURLM_OK) {
            if (curl_multi_select($mh) != -1) {
                do {
                    $mrc = curl_multi_exec($mh, $active);
                } while ($mrc == CURLM_CALL_MULTI_PERFORM);
            }
        }

        foreach($threads as $thread=>$value) {
            $results[$thread] = curl_multi_getcontent($handles[$thread]);
            curl_multi_remove_handle($mh, $handles[$thread]);
            curl_close($handles[$thread]); // Close individual curl handle
        }

        curl_multi_close($mh);
    }
    return $results;
}

This ensures all curl resources are properly closed after use, preventing potential memory issues.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 21:57:43