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

时间:2016-04-20 05:52:11

标签: javascript ecmascript-6 es6-promise

我有一个场景,我要回复一个承诺。 承诺基本上给出了ajax请求的响应。

在拒绝承诺时,它会显示一个错误对话框,显示存在服务器错误。

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

我的代码看起来像这样

locManager.startUpdatingLocation()

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

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

感谢。

6 个答案:

答案 0 :(得分:65)

promise只是一个在Javascript中具有属性的对象。这没有什么神奇之处。因此,如果未能解决或拒绝承诺,则无法从"等待"其他任何事情。这不会导致Javascript中的任何基本问题,因为promise只是一个常规的Javascript对象。如果没有代码保留对promise的引用,那么promise仍将被垃圾收集(即使仍然未决)。

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

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

  

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

     

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

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

答案 1 :(得分:7)

始终解决或拒绝承诺。即使你现在没有使用结果,尽管这样做有效,但这是一个非常糟糕的做法,因为承诺来吞下错误,你的代码变得越复杂,它就越难找到你没有明确完成承诺的几个地方(另外你甚至不知道这是否是问题)。

答案 2 :(得分:4)

我认为如果我们不解决拒绝问题会发生什么?已被回答正确 - 您可以选择是添加.then还是.catch

然而,这段代码好吗?或者有更好的方法来实现这个。我想说有两件事:

如果没有必要将{1}}中的承诺包裹起来,new Promise来电可能会失败,您应该对此采取行动,这样您的主叫方法就不会坐下来等待永远无法解决的承诺。

以下是一个示例(我认为这应该适用于您的业务逻辑,而不是100%确定):

fetch

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

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

不会记录任何内容,因为对makeRequest("http://example", {}) .then(info => console.log("info", info)) .catch(err => console.log("error", err)); 的调用将失败,但http://example处理程序将永远不会执行。

答案 3 :(得分:2)

除非makeRequest的调用者希望履行承诺,否则它的确有效并且不是问题。所以,你在那里违反合同。

相反,您可以推迟承诺,或者(在这种情况下)拒绝状态代码/错误。

答案 4 :(得分:2)

正如其他人所说的那样,如果你不解决/拒绝承诺,这不是一个真正的问题。无论如何,我会解决你的问题有点不同:

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

这意味着我会拒绝所有错误的回复状态,然后在error handler的{​​{1}}处理此问题。

答案 5 :(得分:0)

ECMAScript规范说明了promise和new Promise()的目的:

Promise是一个对象,用作延迟(可能是异步)计算的最终结果的占位符。

25.6.3.1承诺( executor

注意 executor 参数必须是一个函数对象。要求启动并报告此Promise对象表示的可能推迟的操作的完成。

您应该使用承诺来获得未来的价值。此外,为了使代码简洁明了,直接,您应该使用promise获取将来的值,而不要做其他事情。

由于您还将程序控制流(重定向逻辑)混入了Promise的“执行程序”逻辑中,因此Promise不再是“计算结果的占位符”;而是伪装成一个小小的JavaScript程序。

因此,建议不要像普通的JavaScript程序一样编写此JavaScript程序,而不是将其包装在new Promise()中:

async function makeRequest(url, params) {
  let response = await fetch(url, params);
  let { status } = response;
  if (status >= 200 && status < 300) {
    let data = await response.json();
    successLogic(data);
  } else if (status === 401) {
    redirectToLoginPage();
  } else {
    let error = await response.json()
    if (!error.message) {
      error.message = constants.SERVER_ERROR;
    }
    errorLogic({ status, error });
  }
}