Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
优雅地处理“等待”Javascript承诺的拒绝_Javascript_Node.js_Asynchronous_Async Await_Es6 Promise - Fatal编程技术网

优雅地处理“等待”Javascript承诺的拒绝

优雅地处理“等待”Javascript承诺的拒绝,javascript,node.js,asynchronous,async-await,es6-promise,Javascript,Node.js,Asynchronous,Async Await,Es6 Promise,ES2017 async/await的一个好模式是: async function () { try { var result = await some_promised_value() } catch (err) { console.log(`This block would be processed in a reject() callback with promise patterns but this is far more intuiti

ES2017 async/await的一个好模式是:

async function () {
  try {
    var result = await some_promised_value()
  } catch (err) {
    console.log(`This block would be processed in
      a reject() callback with promise patterns
      but this is far more intuitive`)
    return false // or something less obtuse
  }
  result = do_something_to_result(result)
  return result;
}
能够处理这样的错误真的很好。但是如果我想异步获取一个值,我想保护它不被重新分配(例如:数据库会话),但我仍然想使用异步/等待模式(纯粹因为我认为它更直观)

以下操作不起作用,因为常量是块作用域:

async function () {
  try {
    const result = await get_session()
  } catch (err) {
    console.log(`This block should catch any
      instantiation errors.`)
    return false
  }
  // Can't get at result here because it is block scoped.
}
当然,您可以在
try
块中执行函数的其余部分,但这样您就有可能发现错误,而这些错误本应在其他地方漏掉。(例如,我遇到了编写测试的挑战,其中测试失败等错误需要退回到测试套件中,但我想自己处理驱动程序实例化。也许我在这里陷入了某种反模式,因为我没有让这些错误退回到测试套件中。)

很明显,简单的答案是不要在这里使用这种模式。改用承诺和回访。或者使用
var
并避免块作用域
const
let
。但我喜欢重新分配保护的好处,以及出于其他考虑的阻止范围

[问题]:这似乎是一个潜在的解决方案,但其可读性不如
try/catch
。事实上,
try/catch
不会破坏函数作用域,我可以在
try/catch
块中使用
return
,这在我看来更符合
async/await
的精神,为异步代码带来了一种更具过程性的逻辑

理想情况下,您可能希望执行类似于
const x=await y()catch(err)
const x=await y()| | fail
的操作,但我想不出任何类似的流程在语法上是正确的

更新: 根据以下@jmar777的建议,另一个备选方案是:

const x = await y().catch(() => {/*handle errors here*/})
这可能是我在实践中发现的最接近最后两个例子的例子。但它打破了上面示例中阻止下游执行的
返回
范围。这是一种很好的同步处理方式

每个解决方案都有其权衡


我已经用
let
在功能块顶部手动提升变量,作为一个有效的解决方案(如jmar777的回答所述),这仍然是一个有趣的问题,可以看到各种方法,因此我现在将这个问题留待讨论。

您可能对使用
const
的好处有误解。使用
const
声明赋值并不会使该值不变,它只是意味着该常量的值不能更改或重新声明:

const声明创建对值的只读引用。这并不意味着它所持有的值是不可变的,只是变量标识符不能被重新分配。例如,如果内容是对象,这意味着对象本身仍然可以更改。()

在您的示例中,最好在try/catch之外手动提升
结果
绑定:

async function () {
  let result;

  try {
    result = await get_session()
  } catch (err) {
    console.log(`This block should catch any
      instantiation errors.`)
  }

  // do whatever else you need with result here...
}
另一种方法是重新构造代码,使您根本不需要依赖try/catch。例如:

async function () {
  const result = await get_session().catch(someRejectionHandler); 

  // do whatever else you need with result here...
}

请注意,下游代码需要优雅地处理
get\u session()
被拒绝,并且
result
未基于成功响应初始化的情况。这与您最初的示例没有什么不同,但在扫描代码时可能没有那么明显。

几年后回到这个问题,我想到了一个简单得多的答案,回想起来,我不明白为什么我对一个小的try/catch对感兴趣,然后在它之外执行更多的逻辑,而我可以简单地执行所有逻辑并在try语句内部返回

以问题为例,应用该结构将是:

 async function () {
  try {
    const result = await get_session()
    // Do what needs to be done and then:
    return result
  } catch (err) {
    console.log(`This block should catch any
      instantiation errors.`)
    return false
  }
}

如果需要从catch块中的try块访问任何内容,请在出现错误时提示它。当我问这个问题时,可能有一个原因我需要离开try的范围,但我看不到一个场景需要回头看。如果使用try/catch/finally并返回finally,则此解决方案将不起作用。但我认为我在野外根本没有遇到过这种模式

异步/等待不是ES7(ES2016)的一部分。它将成为今年的ES2017发布版的一部分。类似的答案希望能对您有所帮助。另请看啊,我想我误解了“不可变”的语义,而不是
const
的作用。我将修改这个问题以消除混淆。另外,在我编写的原始代码中,
catch
块中有一个
return
,为了防止下游执行,我将更新伪代码以匹配。从
catch
内部返回的能力是我喜欢它而不是
的原因之一。catch
带有回调,它看起来更符合
async/wait
的风格。你的提升解决方案就是我用来让代码工作的解决方案。不过如果还有const就好了。你不需要在尝试中使用return语句吗?@PositiveGuy最有可能。错误处理逻辑不是问题的主题,因此这实际上只是一个try/catch存根,目的是演示手动将
结果提升到更高的范围。