为啥 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/awaitasync 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
对象,该对象将向前提供结果。
async
和 await
您可以使用 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 function
s 返回一个 Promise。 await
关键字将函数的其余部分包装在 .then(…)
中。这里没有await
和async
是等价的:
// 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 回调中返回返回值? [复制]