then()函数是否返回一个反映上一个承诺结果的承诺?

时间:2019-02-15 18:22:27

标签: javascript node.js asynchronous promise async-await

我对诺言并不陌生,已经对其进行了研究。所以我的代码和我的理解:

sql.connect(config).then(function(connection) {
  return connection.request().query('select * from Users')
}).then(function(result) {
  console.dir(result);
  res.send(result);
}).catch((err) => {
  console.log(err);
  res.send(err)
});
}) // extra?

在第一行中,connect方法返回一个promise,以此类推,当我调用函数then如果连接成功)时。 then采用回调,即“ successCB”,“ failureCB”作为参数,它们实际上表示connect承诺返回的结果或错误。是吗?

此外,“ successCB”正在返回承诺(来自.query)。

再次在then返回的先前的诺言上调用

then

then上使用connect()的情况下,then为什么要进行回调,以及如何知道connect的成功,因为connect具有已经返回了结果,即“ successCB”?

3 个答案:

答案 0 :(得分:1)

如果您是正确的人,我不确定100%,但这就是我的解释方式。可以说我们有一个承诺 A

  • 呼叫then() 总是会返回新的承诺(我们称其为 B
  • 如果回调返回承诺 C ,则承诺 B 将解决或失败,并带有承诺 C 的结果。
  • 如果任何回调返回非承诺值 X ,则诺言 B 将使用值 X
  • 进行解析。
  • 如果回调中引发了异常,则诺言 B 将因该异常而失败。
  • 如果主承诺 A 失败,并且未给出失败回调,则承诺 B 也将失败,并出现相同的错误。

我个人觉得学习起来很混乱,因为要完全掌握它需要相当复杂的心理模型。我完全了解这一天的那天就是我编写自己的Promise类的那一天。我建议任何完全希望兑现承诺的人都花些时间来做到这一点。

答案 1 :(得分:0)

  

在第一行中,connect方法返回一个promise,因此,我调用了一个函数then(如果connect成功了)。

几乎:then方法的调用与connect承诺的结果无关。请注意,在调用then方法时,promise最有可能仍未完成。 (很明显)它被同步地称为

  

then接受回调,即successCBfailureCB作为参数,实际上代表了connect承诺返回的结果或错误。是吗?

这些回调由Promise对象注册,并且当Promise解析后,它们中的一个会被调用:它可以实现也可以拒绝。如果诺言永远无法解决,就不会被调用。在您的情况下,您仅提供了一个函数,当诺言履行时将调用该函数。

  

此外,successCB(从.query返回诺言。

是的。在执行外部then时创建的promise将接管此处返回的promise的状态/值。

  再次在then返回的先前的诺言上调用

then

是的,但是再次被立即调用。所有链接的then / catch方法都被同步调用,它们的工作是注册回调并返回Promise。

异步部分是调用相应的回调时。这是级联效果发生的时间。链中的第一个承诺(query())解析后,将调用相应的回调,并且该调用解析(履行或拒绝)then 已经返回的承诺,会触发下一个回调...等等

执行顺序

A部分

  1. sql.connect(config)

    呼叫connect并返回一个诺言

  2. .then(......)

    对A.1的承诺调用then,注册回调并返回承诺

  3. .catch(.....)

    对A.2的承诺调用catch,注册回调并返回承诺。 这恰好是链中的最后一个,所以这个承诺就是整个表达式的价值。

此时同步部分结束。如果调用堆栈上还有其他调用代码,则将执行该代码,但最终调用堆栈将为空。

B部分

然后,一段时间后,发生一个事件,表明A.1的承诺已解决,我们假设它已实现(即成功)。然后执行第一个回调:

  1. connection.request()被执行

    它调用request并返回一个带有query方法的对象(以及其他方法)

  2. .query('select * from Users')被执行

    它使用SQL调用query并返回一个诺言

  3. return被执行

    回调返回B.2的承诺,该承诺与在步骤A.1中创建的承诺链接。

这时,步骤A.1的承诺仍未完成。现在,它的命运与query B.2返回的诺言紧密相关。一旦解决,A.1也将解决(具有相同的状态和值/错误)。

C部分

然后,一段时间后,发生一个事件,表明步骤A.1的承诺已解决,我们假设它已实现。然后执行第二个回调:

  1. console.dir(result)被执行
  2. res.send(result)被执行
  3. 不返回任何内容,因此1.B的诺言实现为值undefined

    此实现会创建要执行的下一个异步作业(D部分)

D部分

  1. catch(A.3)返回的诺言以C.3解析的值来解析,即,它以值undefined来履行。已注册的回调不执行,因为它与该场景无关。

答案 2 :(得分:0)

感谢您的答复,我已经选择了答案。根据大家的意见,这是我进一步了解的。

sql.connect(config).then(function(connection) {
  return connection.request().query('select * from Users')
})

在上面给出的代码中,sql.connect部分正在使用SQL模块来调用connect()方法,该方法应该返回一个promise(如果失败则返回错误,否则为connection对象)。在connect()上,我们调用then()的方法,该方法采用回调函数function(connection)进行注册,以便稍后在connect返回promise的时刻调用(对于successconnection对象)和更高版本

.then(function(result) {
  console.dir(result);
  res.send(result);
}).
在上一个。promise方法的回调函数的.query('select * from Users')部分返回的then()上调用