Javascript 如果您不解决或拒绝承诺会发生什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36734900/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What happens if you don't resolve or reject a promise?
提问by Aniket
I have a scenario where I am returning a promise. The promise is basically triggered by an ajax request.
我有一个场景,我要返回一个承诺。承诺基本上是由 ajax 请求触发的。
On rejecting the promise it shows an error dialog that there is a server error.
在拒绝承诺时,它会显示一个错误对话框,表明存在服务器错误。
What I want to do is when the response code is 401, I neither want to resolve the promise nor reject it (because it already shows the error dialog). I want to simply redirect to the login page.
我想要做的是当响应代码是 401 时,我既不想解决承诺也不想拒绝它(因为它已经显示了错误对话框)。我想简单地重定向到登录页面。
My code looks something like this:
我的代码看起来像这样:
function makeRequest(ur, params) {
return new Promise(function (resolve, reject) {
fetch(url, params).then((response) => {
let status = response.status;
if (status >= 200 && status < 300) {
response.json().then((data) => {
resolve(data);
});
} else {
if (status === 401) {
redirectToLoginPage();
} else {
response.json().then((error) => {
if (!error.message) {
error.message = constants.SERVER_ERROR;
}
reject({ status, error });
});
}
}
});
});
}
As you can see, if the status is 401, I am redirecting to the login page. The promise is neither resolved nor rejected.
如您所见,如果状态为 401,我将重定向到登录页面。承诺既没有解决也没有拒绝。
Is this code OK, or is there any better way to accomplish this?
这段代码可以吗,或者有没有更好的方法来完成这个?
回答by jfriend00
A promise is just an object with properties in Javascript. There's no magic to it. So failing to resolve or reject a promise just fails to ever change the state from "pending" to anything else. This doesn't cause any fundamental problem in Javascript because a promise is just a regular Javascript object. The promise will still get garbage collected (even if still pending) if no code keeps a reference to the promise.
承诺只是一个在 Javascript 中具有属性的对象。它没有魔法。因此,未能解决或拒绝承诺只是无法将状态从“待定”更改为其他任何状态。这不会在 Javascript 中引起任何根本问题,因为 promise 只是一个常规的 Javascript 对象。如果没有代码保留对承诺的引用,承诺仍然会被垃圾收集(即使仍然挂起)。
The real consequence here is what does that mean to the consumer of the promise if its state is never changed? Any .then()
or .catch()
listeners for resolve or reject transitions will never get called. Most code that uses promises expects them to resolve or reject at some point in the future (that's why promises are used in the first place). If they don't, then that code generally never gets to finish its work.
这里真正的结果是,如果承诺的状态永远不会改变,这对承诺的消费者意味着什么?解决或拒绝转换的任何.then()
或.catch()
侦听器将永远不会被调用。大多数使用 Promise 的代码都希望它们在未来的某个时刻解决或拒绝(这就是为什么首先使用 Promise)。如果他们不这样做,那么该代码通常永远无法完成其工作。
It's possible that you could have some other code that finishes the work for that task and the promise is just abandoned without ever doing its thing. There's no internal problem in Javascript if you do it that way, but it is not how promises were designed to work and is generally not how the consumer of promises expect them to work.
您可能有一些其他代码来完成该任务的工作,并且承诺只是被放弃而没有做它的事情。如果你这样做的话,Javascript 中没有内部问题,但这不是 Promise 的设计方式,通常也不是 Promise 的使用者期望它们工作的方式。
As you can see if the status is 401, I am redirecting to login page. Promise is neither resolved nor rejected.
Is this code OK? Or is there any better way to accomplish this.
如您所见,状态是否为 401,我正在重定向到登录页面。Promise 既没有解决也没有拒绝。
这段代码好吗?或者有没有更好的方法来实现这一点。
In this particular case, it's all OK and a redirect is a somewhat special and unique case. A redirect to a new browser page will completely clear the current page state (including all Javascript state) so it's perfectly fine to take a shortcut with the redirect and just leave other things unresolved. The system will completely reinitialize your Javascript state when the new page starts to load so any promises that were still pending will get cleaned up.
在这种特殊情况下,一切正常,重定向是一种特殊且独特的情况。重定向到新的浏览器页面将完全清除当前页面状态(包括所有 Javascript 状态),因此使用重定向的快捷方式并保留其他未解决的问题完全没问题。当新页面开始加载时,系统将完全重新初始化您的 Javascript 状态,因此任何仍待处理的承诺都将被清除。
回答by CodingIntrigue
I think the "what happens if we don't resolve reject" has been answered fine - it's your choice whether to add a .then
or a .catch
.
我认为“如果我们不解决拒绝会发生什么”已经得到了很好的回答 - 您可以选择添加 a.then
还是 a .catch
。
However, Is this code OK? Or is there any better way to accomplish this. I would say there are two things:
但是,这段代码可以吗?或者有没有更好的方法来实现这一点。我想说有两件事:
You are wrapping a Promise in new Promise
when it is not necessary and the fetch
call can fail, you should act on that so that your calling method doesn't sit and wait for a Promise which will never be resolved.
new Promise
当没有必要并且fetch
调用可能失败时,您正在包装一个 Promise ,您应该采取行动,以便您的调用方法不会坐等一个永远不会被解决的 Promise。
Here's an example (I think this should work for your business logic, not 100% sure):
这是一个示例(我认为这应该适用于您的业务逻辑,而不是 100% 确定):
const constants = {
SERVER_ERROR: "500 Server Error"
};
function makeRequest(url,params) {
// fetch already returns a Promise itself
return fetch(url,params)
.then((response) => {
let status = response.status;
// If status is forbidden, redirect to Login & return nothing,
// indicating the end of the Promise chain
if(status === 401) {
redirectToLoginPage();
return;
}
// If status is success, return a JSON Promise
if(status >= 200 && status < 300) {
return response.json();
}
// If status is a failure, get the JSON Promise,
// map the message & status, then Reject the promise
return response.json()
.then(json => {
if (!json.message) {
json.message = constants.SERVER_ERROR;
}
return Promise.reject({status, error: json.message});
})
});
}
// This can now be used as:
makeRequest("http://example", {})
.then(json => {
if(typeof json === "undefined") {
// Redirect request occurred
}
console.log("Success:", json);
})
.catch(error => {
console.log("Error:", error.status, error.message);
})
By contrast, calling your code using:
相比之下,使用以下方法调用您的代码:
makeRequest("http://example", {})
.then(info => console.log("info", info))
.catch(err => console.log("error", err));
Will not log anything because the call to http://example
will fail, but the catch
handler will never execute.
不会记录任何内容,因为调用http://example
将失败,但catch
处理程序永远不会执行。
回答by Fidel90
As others stated it's true that it's not really an issue if you don't resolve/reject a promise. Anyway I would solve your problem a bit different:
正如其他人所说,如果您不解决/拒绝承诺,这确实不是问题。无论如何,我会以不同的方式解决您的问题:
function makeRequest(ur,params) {
return new Promise(function(resolve,reject) {
fetch(url,params)
.then((response) => {
let status = response.status;
if (status >= 200 && status < 300) {
response.json().then((data) => {
resolve(data);
})
}
else {
reject(response);
}
})
});
}
makeRequest().then(function success(data) {
//...
}, function error(response) {
if (response.status === 401) {
redirectToLoginPage();
}
else {
response.json().then((error) => {
if (!error.message) {
error.message = constants.SERVER_ERROR;
}
//do sth. with error
});
}
});
That means I would reject every bad response state and then handle this in your error handler
of your makeRequest
.
这意味着我会拒绝每一个错误的响应状态,然后在你error handler
的makeRequest
.
回答by nullpotent
It works and isn't really a problem, except when a caller of makeRequest
expects of promise to fulfil. So, you're breaking the contract there.
它有效并且不是真正的问题,除非调用者makeRequest
期望承诺实现。所以,你在那里违反了合同。
Instead, you could defer the promise, or (in this case) reject with status code/error.
相反,您可以推迟承诺,或者(在这种情况下)拒绝状态代码/错误。