为啥 fetch 返回 promise 未决?

Posted

技术标签:

【中文标题】为啥 fetch 返回 promise 未决?【英文标题】:Why fetch returns promise pending?为什么 fetch 返回 promise 未决? 【发布时间】:2020-04-11 03:49:30 【问题描述】:

我正在使用 fetch 获取数据,但它一直返回未决的承诺。我看过很多关于这个问题的帖子,并尝试了所有的可能性,但没有解决我的问题。我想知道为什么 fetch 简要地返回 promise 为待处理状态 fetch 返回待处理状态的可能情况是什么?

我的一段代码供参考:

fetch(res.url).then(function(u) 
    return u.json();
)
.then(function(j)  
    console.log(j); 
);

【问题讨论】:

为什么不会返回一个待处理的 Promise?为什么这是一个问题?提取将发出网络请求,它是非阻塞的,因此是异步的。 抱歉,promise 的哪一部分是待处理的? console.log(j); ?还是别的什么? 一个承诺将总是一开始是pending 它是异步的,所以它必须返回一个待处理的承诺,然后你可以解决/拒绝 假设你派我去商店买些牛奶。在我带着牛奶回来之前,那份工作是悬而未决的。我回来后,它就完成了。 JS 承诺也是如此。您正在向远程服务器发送请求。在返回请求的数据之前,它是挂起的。一旦数据返回,它就完成了。 【参考方案1】:

fetch() 是网络操作。为避免在收到网络回复之前挂起,我们将其推迟到后台处理,并向自己保证它最终会完成。

所以fetch(url).then((data) => data.json()) 意味着我们获取 url,等待数据进来,获取数据的 json 表示并等待(data.json() 也是一个承诺)

在我们得到结果之前,promise 处于pending 状态。服务器还没有回复我们的请求。

-- 阅读 cmets,添加错误处理程序可能会很好,因为这就是为什么当前 fetch 不做任何事情的原因: fetch().then((data) => data.json()).catch((error) => console.log(error))

【讨论】:

或更好地切换到使用 async/await async foo() try const res = await fetch(); const result = await res.json(); catch (e) console.log.error; ); foo(); 也是一种可能。使其更易于阅读,但 OP 使用 .then 链接,所以我按照他的示例进行操作 我没有批评你的回答。我在向提问者建议另一种解决方案。我发现 async/await 比 .then 更容易使用,所以当我看到我的用户正在为 .then 苦苦挣扎时,我通常建议切换到 async/await。总体而言,IMO 更容易。 我没有把它当作批评,我也同意你在这里的陈述:) 你的 (data.json() 也是一个承诺) 为我节省了很多时间哈哈我不知道【参考方案2】:

Promises 是一种允许调用者在等待函数结果时做其他工作的方法。

请参阅 MDN 上的 Promises 和 Using Promises:

Promise 处于以下状态之一:

待定:初始状态,既不满足也不拒绝。 fulfilled:表示操作成功完成。 rejected:表示操作失败。

fetch(url) 返回一个Promise 对象。它允许使用可以响应结果值(响应请求)的.then(…) 将“侦听器”附加到它。 .then(…) 再次返回 Promise 对象,该对象将向前提供结果。

asyncawait

您可以使用 JS 语法糖来使用 Promises:

async function my_async_fn(url) 
    let response = await fetch(url);
    console.log(response); // Logs the response
    return response;
)

console.log(my_async_fn(url)); // Returns Promise

async functions 返回一个 Promise。 await 关键字将函数的其余部分包装在 .then(…) 中。这里没有awaitasync是等价的:

// This function also returns Promise
function my_async_fn(url) 
    return fetch(url).then(response => 
        console.log(response); // Logs the response
        return response;
    );
)

console.log(my_async_fn(url)); // Returns Promise

再次查看 MDN 上的 article on Promises。

【讨论】:

【参考方案3】:

正如一位上层 cmets 所说,fetch() 是一个在网络处理请求时调用.then() 的承诺。这个回调中的参数是另一个promise,当我们得到服务器的响应时会调用$.then()

也许你应该尝试这样的事情:

fetch(res.url)
    .then(function(serverPromise) 
      serverPromise.json()
        .then(function(j)  
          console.log(j); 
        )
        .catch(function(e)
          console.log(e);
        );
    )
    .catch(function(e)
        console.log(e);
      );

或用 lambda 表示法:

fetch(res.url)
    .then((serverPromise) => 
      serverPromise.json()
        .then((j) => console.log(j))
        .catch((e) => console.log(e))
    )
    .catch((e) => console.log(e));

这是我第一次在 *** 上发帖,如果我犯了任何错误或者您有任何建议,请告诉我,谢谢!

【讨论】:

以上是关于为啥 fetch 返回 promise 未决?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Body.json() 返回一个 Promise? [复制]

fetch函数返回promise而不是对象[重复]

如何使用 fetch 从 Promise 回调中返回返回值? [复制]

[RN] React Native Fetch请求设置超时

如何在从 Fetch Api 返回的 Promise 对象中获取错误值?

Node-fetch 返回 Promise <pending> 而不是所需的数据 [重复]