链接承诺并在它们之间传递参数

Chaining Promises and Passing Parameters between Them

我是 Node/Express 的新手,我正在尝试使用 Promises 来执行对 Apple 的 CloudKit JS API 的连续 API 调用。

我不清楚如何按顺序排列函数并将它们各自的 return 值从一个函数传递到下一个函数。

这是我目前的情况:

var CloudKit = require('./setup')

//----
var fetchUserRecord = function(emailConfirmationCode){
  var query = { ... }

  // Execute the query
  CloudKit.publicDB.performQuery(query).then(function (response) {
    if(response.hasErrors) {
      return Promise.reject(response.errors[0])
    }else if(response.records.length == 0){
      return Promise.reject('Email activation code not found.')
    }else{
      return Promise.resolve(response.records[0])
    }
  })
}

//-----
var saveRecord = function(record){
  // Update the record (recordChangeTag required to update)
  var updatedRecord = { ... }

  CloudKit.publicDB.saveRecords(updatedRecord).then(function(response) {
    if(response.hasErrors) {
      Promise.reject(response.errors[0])
    }else{
      Promise.resolve()
    }
  })
}

//----- Start the Promise Chain Here -----
exports.startActivation = function(emailConfirmationCode){

  CloudKit.container.setUpAuth() //<-- This returns a promise
  .then(fetchUserRecord) //<-- This is the 1st function above
  .then(saveRecord(record)) //<-- This is the 2nd function above
    Promise.resolve('Success!')
  .catch(function(error){
    Promise.reject(error)
  })

}

我在快结束时收到错误消息:.then(saveRecord(record)),它说 record 未定义。我认为它会以某种方式从先前的承诺中得到 returned。

看起来这应该比我做的更简单,但我很困惑。当每个 Promise 都有不同的 resolve/reject 结果时,如何让多个 Promise 像这样链接在一起?

代码中几乎没有问题。

首先:您必须将函数传递给 .then() 但实际上您传递的是函数调用的结果:

.then(saveRecord(record))

此外 saveRecord(record) 从技术上讲可能 return 一个函数,因此这样的声明可能有效,但您的情况似乎并非如此。所以你只需要

.then(saveRecord)

另一个问题是 return 从 saveRecordfetchUserRecord 函数内部什么也没有。

最后,您不需要 return 包装器 Promise.resolve 从内部 .then:您可以 return 只是转换数据,它将通过链接向前传递.

var CloudKit = require('./setup')

//----
var fetchUserRecord = function(emailConfirmationCode){
  var query = { ... }

  // Execute the query
  return CloudKit.publicDB.performQuery(query).then(function (response) {
    if(response.hasErrors) {
      return Promise.reject(response.errors[0]);
    }else if(response.records.length == 0){
      return Promise.reject('Email activation code not found.');
    }else{
      return response.records[0];
    }
  })
}

//-----
var saveRecord = function(record){
  // Update the record (recordChangeTag required to update)
  var updatedRecord = { ... }

  return CloudKit.publicDB.saveRecords(updatedRecord).then(function(response) {
    if(response.hasErrors) {
      return Promise.reject(response.errors[0]);
    }else{
      return Promise.resolve();
    }
  })
}

//----- Start the Promise Chain Here -----
exports.startActivation = function(emailConfirmationCode){

  return CloudKit.container.setUpAuth() //<-- This returns a promise
    .then(fetchUserRecord) //<-- This is the 1st function above
    .then(saveRecord) //<-- This is the 2nd function above
    .catch(function(error){});
}

不要忘记 return 转换后的数据或新的承诺。否则 undefined 将被 return 链接到下一个链接函数。

由于@skyboyer 帮助我弄清楚了发生了什么,我会将他们的回答标记为正确的。

我不得不稍微调整一下,因为我需要将返回值传递给我的承诺链中的后续函数。这是我结束的地方:

exports.startActivation = function(emailConfirmationCode){
  return new Promise((resolve, reject) => {

    CloudKit.container.setUpAuth()
      .then(() => {
        return fetchUserRecord(emailConfirmationCode)
      })
      .then((record) => {
        resolve(saveRecord(record))
      }).catch(function(error){
        reject(error)
      })

  })
}