PHP cURL异步API改造求助:需等待HTTP 200及状态校验
Hey there! Let's walk through refactoring your PHP cURL code to fit that asynchronous API workflow. I’ll break this down into clear, reusable functions with comments so even if you’re new to cURL, you can follow along easily.
1. Asynchronous API Workflow Breakdown
First, let's align on the exact steps we need to implement:
- Send an initialization request to kick off the async process
- Wait (or poll) by sending status check requests until the API returns
Completedstatus- If status is
Processing, retry after a short delay - Stop retrying after a set number of attempts to avoid infinite loops
- If status is
- Only use the data once the status confirms it’s ready
2. Refactored PHP cURL Code
Here’s a complete, production-ready implementation with error handling and retry logic:
<?php /** * Send initialization request to the async API * @param string $initUrl URL for initialization endpoint * @param array $initData Data to send with initialization request * @return string|null Returns the job ID if successful, null on failure */ function sendInitRequest(string $initUrl, array $initData): ?string { $ch = curl_init($initUrl); // Set cURL options curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($initData), CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', // Add any auth headers here, e.g., 'Authorization: Bearer YOUR_TOKEN' ], CURLOPT_TIMEOUT => 30, // Timeout after 30 seconds ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); curl_close($ch); // Handle errors if ($error) { error_log("Initialization cURL error: " . $error); return null; } // Check for successful HTTP status (200 OK) if ($httpCode !== 200) { error_log("Initialization failed with HTTP code: " . $httpCode . ", Response: " . $response); return null; } // Parse JSON response $responseData = json_decode($response, true); if (json_last_error() !== JSON_ERROR_NONE) { error_log("Failed to parse initialization response: " . json_last_error_msg()); return null; } // Return the job ID (adjust key based on your API's response) return $responseData['job_id'] ?? null; } /** * Check status of the async job * @param string $statusUrl URL for status query endpoint * @param string $jobId ID returned from initialization request * @return array|null Returns status and data if successful, null on failure */ function checkJobStatus(string $statusUrl, string $jobId): ?array { // Build query URL with job ID (adjust based on your API's expected format) $queryUrl = $statusUrl . "?job_id=" . urlencode($jobId); $ch = curl_init($queryUrl); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', // Add auth headers here if needed ], CURLOPT_TIMEOUT => 10, // Shorter timeout for status checks ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); curl_close($ch); if ($error) { error_log("Status check cURL error: " . $error); return null; } if ($httpCode !== 200) { error_log("Status check failed with HTTP code: " . $httpCode . ", Response: " . $response); return null; } $responseData = json_decode($response, true); if (json_last_error() !== JSON_ERROR_NONE) { error_log("Failed to parse status response: " . json_last_error_msg()); return null; } // Return status and data (adjust keys based on your API) return [ 'status' => $responseData['status'] ?? null, 'data' => $responseData['data'] ?? null ]; } // ------------------------------ // Main Execution Flow // ------------------------------ // Configuration - adjust these values for your API $INIT_API_URL = "https://your-api.com/initialize-job"; $STATUS_API_URL = "https://your-api.com/check-job-status"; $MAX_RETRIES = 10; // Max number of status checks $RETRY_DELAY = 2; // Seconds between retries $initPayload = [ // Your initialization data here, e.g., 'input' => 'your-data' ]; // Step 1: Send initialization request $jobId = sendInitRequest($INIT_API_URL, $initPayload); if (!$jobId) { die("Failed to initialize async job"); } echo "Job initialized with ID: " . $jobId . "\n"; // Step 2: Poll for job completion $currentRetry = 0; $jobCompleted = false; $finalData = null; while ($currentRetry < $MAX_RETRIES && !$jobCompleted) { // Wait before checking status (skip first delay if API returns immediately) if ($currentRetry > 0) { sleep($RETRY_DELAY); } $statusResponse = checkJobStatus($STATUS_API_URL, $jobId); if (!$statusResponse) { $currentRetry++; continue; } switch ($statusResponse['status']) { case 'Completed': $jobCompleted = true; $finalData = $statusResponse['data']; break; case 'Processing': echo "Job still processing... Retry " . ($currentRetry + 1) . "/" . $MAX_RETRIES . "\n"; $currentRetry++; break; default: error_log("Unexpected job status: " . $statusResponse['status']); $currentRetry = $MAX_RETRIES; // Exit loop break; } } // Step 3: Process the result if ($jobCompleted && $finalData) { echo "Job completed successfully!\n"; // Use your data here, e.g., print_r($finalData); print_r($finalData); } else { echo "Job timed out or failed after " . $MAX_RETRIES . " retries\n"; } ?>
3. Key Improvements & Important Notes
Let’s go over the critical parts that make this code robust:
- Modular Functions: Split initialization and status checking into separate functions for reusability and readability
- Error Handling: Catches cURL errors, invalid HTTP status codes, and JSON parsing failures (logs errors for debugging)
- Controlled Retries: Uses
MAX_RETRIESandRETRY_DELAYto avoid overwhelming the API or getting stuck in an infinite loop - Strict Status Validation: Only proceeds when the API explicitly returns
Completed; handles unexpected statuses gracefully - Configurable Values: All API URLs and retry settings are at the top for easy adjustment
- URL Encoding: Uses
urlencode()for the job ID to avoid issues with special characters in the URL
4. Quick Adjustments for Your API
You’ll need to tweak a few parts to match your specific API:
- Update
$INIT_API_URLand$STATUS_API_URLto your actual endpoints - Adjust the auth headers in both functions if your API requires authentication (e.g., Bearer tokens, API keys)
- Modify the JSON key names (like
job_id,status,data) to match what your API returns - Adjust
$MAX_RETRIESand$RETRY_DELAYbased on your API’s expected processing time (10 retries at 2s each = 20s total wait, which matches your original requirement)
内容的提问来源于stack exchange,提问作者gdr39
相关产品推荐
相关产品推荐

