如果我们不解决或拒绝承诺会发生什么

Ani*_*ket 55 javascript ecmascript-6 es6-promise

我有一个场景,我将返回一个承诺.承诺基本上给出了ajax请求的响应.

在拒绝承诺时,它显示错误对话框,表明存在服务器错误.

我想要做的是当响应代码是401时,我既不想解决承诺也不想拒绝它(因为它显示错误对话框).我想简单地重定向到登录页面.

我的代码看起来像这样

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});
                    })    
                }
            }

        })
    });
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的状态是401,我正在重定向到登录页面.承诺既未得到解决也未被拒绝.

这段代码好吗?或者有更好的方法来实现这一目标.

谢谢.

jfr*_*d00 79

承诺只是Javascript中具有属性的对象.这没有什么神奇之处.因此,未能解决或拒绝承诺只是无法将状态从"待定"更改为其他任何内容.这不会导致Javascript中的任何基本问题,因为promise只是一个常规的Javascript对象.如果没有代码保留对promise的引用,则promise仍会收集垃圾(即使仍处于挂起状态).

这里的真正后果是,如果它的状态永远不会改变,这对承诺的消费者意味着什么呢?解决或拒绝转换的任何.then().catch()侦听器永远不会被调用.大多数使用promises的代码都希望它们在将来的某个时刻得到解决或拒绝(这就是为什么首先使用promises的原因).如果他们不这样做,那么该代码通常永远不会完成它的工作.

您可能有一些其他代码可以完成该任务的工作,并且承诺只是放弃而不做任何事情.如果你这样做,Javascript中没有内部问题,但并不是承诺的设计方式如何,并且通常不是承诺的消费者期望它们如何工作.

正如您所看到的状态是401,我正在重定向到登录页面.承诺既未得到解决也未被拒绝.

这段代码好吗?或者有更好的方法来实现这一目标.

在这种特殊情况下,一切正常,重定向是一种有点特殊和独特的情况.重定向到新的浏览器页面将完全清除当前页面状态(包括所有Javascript状态),因此使用重定向的快捷方式完全没问题,只留下其他未解决的问题.当新页面开始加载时,系统将完全重新初始化您的Javascript状态,因此任何仍未决的承诺将被清除.

  • 如您所述,重定向到新的浏览器页面将完全清除当前页面状态(包括所有Javascript状态)。但是,如果我在单页面应用程序中重定向,将会发生什么。我正在使用ReactJS。因此,将没有新的浏览器页面,只是一个不同的视图。在这种情况下,采用重定向的快捷方式并保留其他未解决的内容是否完美? (2认同)

Cod*_*gue 6

我认为“如果我们不解决拒绝会发生什么”已经得到了很好的回答 - 您可以选择添加 a.then还是 a .catch

但是,这段代码可以吗?或者有没有更好的方法来实现这一点。我想说有两件事:

new Promise当没有必要并且fetch调用可能失败时,您正在包装 Promise ,您应该采取行动,以便您的调用方法不会坐等永远不会解决的 Promise。

这是一个示例(我认为这应该适用于您的业务逻辑,而不是 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);
  })
Run Code Online (Sandbox Code Playgroud)

相比之下,使用以下方法调用您的代码:

makeRequest("http://example", {})
  .then(info => console.log("info", info))
  .catch(err => console.log("error", err));
Run Code Online (Sandbox Code Playgroud)

不会记录任何内容,因为调用http://example将失败,但catch处理程序永远不会执行。

  • 我只是想避免 if(typeof json === "undefined") { // 发生重定向请求 } 原因是 makeRequest 被许多其他函数调用,我必须在调用它的每个函数中进行检查。 (2认同)