【问题标题】:promise chaining reject承诺链拒绝
【发布时间】:2019-11-25 10:18:14
【问题描述】:

我正在编写这个链式承诺。

首先,当一个按钮被点击时,它会检查一个文件 url 是否存在:

如果不是,则拒绝,然后在警报中显示响应状态。

如果是,则通过 webapi 更新数据库,然后更新反应状态。

我面临的问题是,即使我在 validateResponse 函数中拒绝,它仍然会在下一个运行。

我觉得应该直接去catch。

此外,下面调用 webapi 的代码似乎不太好,一个 then 中的 promise 等等。整个代码似乎也不清楚?这是更好的方法吗?

onClick: (event, row) => {


function validateResponse(response) {
  if (!response.ok) { // assume it is the reject case.
    console.log("file not ready");
    return Promise.reject(response.statusText);
  } else {
    window.open(response.url, '_blank', 'location=yes,height=500,width=600,scrollbars=no,status=yes')
    return response;
  }

}


fetch(row.fileurl, {
  method: 'HEAD'
})
.then(validateResponse)

.then(console.log("== this line not printed, due to rejected."))

.then(row.linked = 1)

.then( 
    fetch(this.server_url+'/file/linked', { method: 'POST', body: JSON.stringify(row),  headers: { 'Content-Type': 'application/json' }, })
      .then(res => {
        console.log("== it should be rejected!, why printed this line2")
        if (res.status==200) {
          this.setState({ row });
        } else {
          row.checked = 0;
          throw Error(res.status);
        }

  })                            

)
.catch(function (error) {
    alert("Sorry, the file is not avaliable yet")
});


}

还有一个问题:

.then(() => row.linked = 1)
.then(() => fetch(this.server_url+'/file/linked', { method: 'POST', body: JSON.stringify(row),  headers: { 'Content-Type': 'application/json' }, })

如何将其合二为一?

.then(() => row.linked = 1 && fetch(this.server_url+'/file/linked', { method: 'POST', body: JSON.stringify(row),  headers: { 'Content-Type': 'application/json' }, })

这是一种更好/正确的方法吗?

【问题讨论】:

  • .then 将函数作为参数,但您将指令放入其中。 .then(() => console.log(/*...*/))
  • validateResponse()代码滚动到promise链后,你可以得到更好的优化。
  • 在完全同步操作之后,您不需要额外的.then()。您有两个异步操作,fetch(row.fileurl, ...)fetch(this.server_url + '/file/linked', ...),因此一切都将简化为两个 then 和一个 catch。

标签: javascript reactjs promise


【解决方案1】:

返回 Promise.reject 应该可以正常工作。

问题是,当您未在 .then 中指定返回值时,默认情况下会使用未定义的值解析承诺。

在您的情况下,您应该更改您的 validateResponse 以便它返回被拒绝的承诺:

return Promise.reject(response.statusText);

查看this了解更多信息。

==================

编辑:尝试使用此代码

onClick: (event, row) => {
  function validateResponse(response) {
    if (!response.ok) { // assume it is the reject case.
      console.log("file not ready");
      return Promise.reject(response.statusText);
    } else {
      window.open(response.url, '_blank', 'location=yes,height=500,width=600,scrollbars=no,status=yes')
      return response;
    }
  }

  fetch(row.fileurl, {
    method: 'HEAD'
  })
  .then(validateResponse)
  .then(() => console.log("== this line not printed, due to rejected."))
  .then(() => row.linked = 1)
  .then(() => fetch(this.server_url+'/file/linked', { method: 'POST', body: JSON.stringify(row),  headers: { 'Content-Type': 'application/json' }, })
    .then(res => {
      console.log("== it should be rejected!, why printed this line2")
      if (res.status==200) {
        this.setState({ row });
      } else {
        row.checked = 0;
        throw Error(res.status);
      }
    })
  )
  .catch(function (error) {
      alert("Sorry, the file is not avaliable yet")
  });
}

==========================

Edit2:.then 接受一个函数作为回调。这意味着您可以根据需要将其放入一个大函数中:

onClick: (event, row) => {
  function validateResponse(response) {
    if (!response.ok) { // assume it is the reject case.
      console.log("file not ready");
      return Promise.reject(response.statusText);
    } else {
      window.open(response.url, '_blank', 'location=yes,height=500,width=600,scrollbars=no,status=yes')
      return response;
    }
  }

  fetch(row.fileurl, {
    method: 'HEAD'
  })
  .then(validateResponse)
  .then(() => {
    console.log("== this line not printed, due to rejected.");
    row.linked = 1;
    return fetch(this.server_url+'/file/linked', { method: 'POST', body: JSON.stringify(row),  headers: { 'Content-Type': 'application/json' }, })
      .then(res => {
        console.log("== it should be rejected!, why printed this line2")
        if (res.status==200) {
          this.setState({ row });
        } else {
          row.checked = 0;
          throw Error(res.status);
        }
      })
  })
  .catch(function (error) {
      alert("Sorry, the file is not avaliable yet")
  });
}

【讨论】:

  • 谢谢,我尝试添加return,但还是到了这一行:console.log("== it should be denied!, why print this line2")
  • @manhon 您没有将回调传递给最后一个.then(),您甚至在创建承诺链之前就在那里调用了fetch()。您的console.log("== this line not printed, due to rejected.") 和您的row.linked = 1 也是如此...
  • 你能用固定的代码回复吗,我试了好几个小时还是无法理解。>
  • 非常感谢,它有效!我可以再问一个问题吗?我刚刚将问题添加到第一篇文章中。
  • @Flezey 非常感谢!我现在修正了我对承诺的糟糕理解。非常感谢!
【解决方案2】:

您没有在回调中调用您的第二次提取,这导致提取立即触发。

function someFunc() {
    // You are invoking the second fetch immediately
    fetch("example.com")
        .then(validate)
        .then(fetch("somewhere.com"))

    // You need to invoke it as a callback
    fetch("example.com")
        .then(validate)
        .then(() => fetch("somewhere.com"))

    // Or with non-arrow
    fetch("example.com")
        .then(validate)
        .then(function() {
            return fetch("somewhere.com");
        });
}

【讨论】:

    猜你喜欢
    • 2013-09-16
    • 1970-01-01
    • 2021-05-31
    • 1970-01-01
    • 2018-02-11
    • 2017-09-04
    • 2019-04-09
    • 2017-03-12
    • 2015-08-26
    相关资源
    最近更新 更多