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

如何为含链式调用的Promise函数实现实时进度日志输出?

How to Track Real-Time Progress in a Promise Chain

Great question! Tracking progress in promise chains—especially when they involve iterative API calls—can be tricky since promises themselves only resolve once. Here's how you can modify your code to add real-time progress updates tailored to your scenario:

Core Idea

We need to inject progress notifications at key points in your promise chain:

  • When the process starts
  • After each sub-task (like individual API calls in an iterator) completes
  • When the entire chain finishes

We'll use a simple progress tracker utility to manage percentage calculations and trigger status updates, then integrate it into your promise functions and chain.

Step 1: Build a Progress Tracker Utility

First, create a reusable tracker to handle progress math and status callbacks:

// A simple utility to manage progress tracking
function ProgressTracker(totalSteps, onStatusUpdate) {
  let currentStep = 0;

  // Notify when the process starts
  this.start = () => onStatusUpdate('starting');

  // Call this after each sub-task completes to update progress
  this.markStepComplete = (message = 'in progress...') => {
    currentStep++;
    const completionPercent = Math.round((currentStep / totalSteps) * 100);
    onStatusUpdate(`${completionPercent}% ${message}`);
  };

  // Notify when the entire process finishes
  this.complete = () => onStatusUpdate('100% completed');
}

Step 2: Modify Your Promise Functions to Report Progress

Update your promise1 and promise2 to accept the progress tracker, so they can report progress during iterative tasks:

// Example promise1 with an iterative API call loop
function promise1(progressTracker) {
  return new Promise(async (resolve) => {
    // Simulate 3 API calls (adjust this to your actual iterator count)
    const apiEndpoints = ['/api/user-data', '/api/settings', '/api/history'];
    
    for (const endpoint of apiEndpoints) {
      // Simulate API request (replace with your actual fetch/axios call)
      await fetch(endpoint);
      // Update progress after each API call finishes
      progressTracker.markStepComplete(`finished ${endpoint}`);
    }

    resolve('promise1 completed');
  });
}

// Example promise2 with iterative tasks
function promise2(progressTracker) {
  return new Promise(async (resolve) => {
    const apiEndpoints = ['/api/summary', '/api/export'];
    
    for (const endpoint of apiEndpoints) {
      await fetch(endpoint);
      progressTracker.markStepComplete(`finished ${endpoint}`);
    }

    resolve('promise2 completed');
  });
}

Step 3: Integrate the Tracker into Your Promise Chain

Modify your promiseChain function to initialize the tracker and pass it through the chain. Since you mentioned res.json, we'll assume you're using Node.js/Express—note that you can't call res.json() multiple times (it closes the response), so we'll use res.write() to send chunked updates instead:

var promiseChain = function(res) {
  // Calculate total steps: 3 from promise1 + 2 from promise2 = 5
  const totalSteps = 5;

  // Initialize tracker: pass a callback to send status updates via HTTP
  const progressTracker = new ProgressTracker(totalSteps, (status) => {
    // Send status as chunked JSON (client can listen for these chunks)
    res.write(JSON.stringify({ status }) + '\n');
  });

  // Trigger the starting status
  progressTracker.start();

  // Run the promise chain with progress tracking
  promise1(progressTracker)
    .then(() => promise2(progressTracker))
    .then(() => {
      progressTracker.complete();
      res.end(); // Close the HTTP response once done
    })
    .catch((error) => {
      // Send error status if something goes wrong
      res.write(JSON.stringify({ status: `Error: ${error.message}` }) + '\n');
      res.end();
    });
};

Simplified Version (No Iterative Tasks)

If your promise chain doesn't have internal iterators and just has two top-level promises, you can simplify the tracking:

var promiseChain = function(res) {
  const totalTasks = 2;
  let completedTasks = 0;

  // Send starting status
  res.write(JSON.stringify({ status: 'starting' }) + '\n');

  promise1()
    .then(() => {
      completedTasks++;
      const percent = (completedTasks / totalTasks) * 100;
      res.write(JSON.stringify({ status: `${percent}% completed promise1` }) + '\n');
      return promise2();
    })
    .then(() => {
      res.write(JSON.stringify({ status: '100% completed all tasks' }) + '\n');
      res.end();
    });
};

Key Notes

  • HTTP Response Limitation: As mentioned, res.json() can only be called once per request. Using res.write() sends chunked data, which the client can parse incrementally. For frontend clients, you can use fetch with a readable stream to listen for these updates.
  • Third-Party Promises: If you can't modify the original promise functions, wrap them in a helper to inject progress tracking:
    function trackPromise(promiseFn, tracker, completionMessage) {
      return promiseFn().then(result => {
        tracker.markStepComplete(completionMessage);
        return result;
      });
    }
    
  • Frontend Usage: If you're working in the browser instead of Node.js, replace the res.write() callback with code that updates your UI (e.g., document.getElementById('progress').textContent = status).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:26:10