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

关于Fetch与Promise的困惑:new Promise相关用法疑问

Hey Bob, let’s break this down step by step— I’ve been exactly where you are, staring at Promise code feeling like it’s some kind of asynchronous black magic. Let’s unpack your questions one by one:

What is new Promise()?

Think of new Promise() as a wrapper for asynchronous work that lets you manually control when that work is marked as "success" or "failure". When you create a new Promise, you pass a callback function that gets two special arguments: resolve and reject.

  • resolve(result): Call this when your asynchronous task finishes successfully. It tells the Promise to transition to a "fulfilled" state, and passes the result to any .then() handlers attached to it.
  • reject(error): Call this when something goes wrong. It moves the Promise to a "rejected" state, passing the error to any .catch() handlers.

The Promise itself acts as a middleman between your asynchronous code and the code that needs to use its result.

Do you need to use new Promise()?

Most of the time, no— especially when using modern APIs like fetch(), which already returns a Promise out of the box. That’s why people say you don’t need to wrap fetch() in a new Promise (more on that Stack Overflow example later).

You only need new Promise() in two main scenarios:

  1. Wrapping legacy asynchronous APIs: Tools like setTimeout, XMLHttpRequest, or older library functions that don’t return Promises natively. For example, turning a callback-based setTimeout into a Promise:
    function wait(ms) {
      return new Promise((resolve) => {
        setTimeout(() => resolve("Done waiting!"), ms);
      });
    }
    
    // Now you can use .then() instead of callbacks
    wait(1000).then(message => console.log(message));
    
  2. Customizing asynchronous flow: When you need to manually control when a Promise succeeds or fails, beyond what a built-in API provides. For example, if you need to run multiple checks before marking a task as complete, or if you want to unify error handling for multiple steps.

When should you use new Promise()?

Let’s use your Stack Overflow example to clarify. The code wraps fetch() in a new Promise like this:

function get(url) {
  console.log('Making fetch() request to: ' + url);
  let promise = new Promise((resolve, reject) => {
    fetch(url)
      .then(res => {
        if (!res.ok) { // Check for HTTP errors (like 404/500)
          reject(new Error(`Status code: ${res.status}`));
        }
        return res.json();
      })
      .then(data => resolve(data))
      .catch(err => reject(err));
  });
  return promise;
}

This is technically redundant— you could rewrite it without new Promise() and get the same result:

function get(url) {
  console.log('Making fetch() request to: ' + url);
  return fetch(url)
    .then(res => {
      if (!res.ok) throw new Error(`Status code: ${res.status}`);
      return res.json();
    });
}

The original example probably exists to demonstrate how resolve/reject work, or maybe to add custom logging/error handling that feels more explicit. In real-world code, the second version is cleaner.

So use new Promise() only when you don’t have a Promise-ready API to work with, or when you need fine-grained control over when the Promise settles.

Assigning to a variable vs returning from a function

There’s a key difference here:

  • Assigning to a variable: The Promise executes immediately when it’s created. For example:
    // This runs right away, even if you don't call .then() yet
    let immediatePromise = new Promise((resolve) => {
      console.log("Promise started!");
      setTimeout(resolve, 1000);
    });
    
  • Returning from a function: The Promise only executes when you call the function. This is much more flexible for reusable logic:
    // Nothing runs until you call runLater()
    function runLater() {
      return new Promise((resolve) => {
        console.log("Promise started!");
        setTimeout(resolve, 1000);
      });
    }
    
    // Now it runs
    runLater().then(() => console.log("Done!"));
    

In almost all cases, returning a Promise from a function is better— it lets you control when the asynchronous work starts, and makes your code reusable.

When and how to call resolve() and reject()

You call these functions inside the Promise’s callback when your asynchronous task reaches a conclusion:

  • Call resolve() when the task succeeds: pass the data you want to send to .then() handlers.
  • Call reject() when the task fails: pass an Error object (or any value) to .catch() handlers.

Here’s a concrete example with XMLHttpRequest (a legacy API that doesn’t return Promises):

function makeRequest(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        // Success: send the response data to .then()
        resolve(xhr.responseText);
      } else {
        // Failure: send an error to .catch()
        reject(new Error(`Request failed: ${xhr.status}`));
      }
    };
    xhr.onerror = () => {
      // Network error: reject with an error
      reject(new Error("Network connection failed"));
    };
    xhr.send();
  });
}

Without new Promise(), you’d be stuck using callbacks for this— wrapping it lets you use the cleaner .then()/.catch() syntax.

Quick recap for your fetch confusion

You’re right about fetch()’s behavior:

  • .catch() only triggers for network errors (like a down server or no internet).
  • To handle HTTP errors (404, 500), you need to check res.ok or res.status in the first .then() and throw an error (which will then trigger .catch()).

You don’t need new Promise() for this— just chain your .then() handlers and throw errors when needed, like the simplified get() function I wrote earlier.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:33:33