繁体   English   中英

我的graphql服务器变异返回空值

[英]my graphql server mutation return null value

我在检索突变结果时遇到了挑战。 我需要创建一个数据库记录,并发送一封电子邮件通知用户注册成功。 因为电子邮件的发送和数据库更新都是服务器端的,所以我想两者都在同一突变中进行。 如果电子邮件失败,则不能更新数据库。 所以我有以下突变:

Mutation: {
        createDealer(_, params) {
            console.log("params: " + JSON.stringify(params));

            bcrypt.genSalt(10, function(err, salt) {
                bcrypt.hash(params.dealer.password, salt, function(err, hash) {
                    // Store hash in your password DB.
                    console.log("hashed password " + params.dealer.password)
                    params.dealer.password = hash;
                    console.log("hashed password " + params.dealer.password + " Hash: " + hash);
                    let session = driver.session();


                    let query = "CREATE (d:Dealer {email:$dealer.email}) SET d += $dealer RETURN d";
                    let here = "here".link("mymail@example.com");

                    let messageObj = {
                        to: params.dealer.email,
                        subject: 'Dealer Registration',
                        text: `Thank you for signing up. To complete and activate your registration please click ${here}.`
                    }

                    return (sendEmail(messageObj))
                        .then(data => {
                            console.log('SendMail data....' + JSON.stringify(data));
                            return session.run(query, params)
                        })
                        .then(result => {
                            console.log('SendNeo4j data....' + JSON.stringify(result));
                            return result.records[0].get("d").properties
                        })
                        .catch((err) => {
                            console.log(err);
                        });
                    //});
                });
            }); // genSalt
        } // Create Dealer
    }, // Mutation

甚至以为两个动作都成功了,我似乎无法检索结果。 我得到以下内容的“未定义”:console.log('SendMail data ....'+ JSON.stringify(data)); 而console.log('SendNeo4j data ....'+ JSON.stringify(result)); 确实显示正确的数据

但graphiql会为突变返回“ null”。 这是graphiql突变:

mutation CreateDealer($dealer: DealerInput!) {
  createDealer(dealer: $dealer) {
    email
    name
  }
}

当然还有DealerInput变量。

我已经阅读了可以从查询/变异中检索多个结果的位置,但不确定如何运行。 在这里,我需要Angular / apollo前端的sendEmail和db update的结果。...我想使graphiql成像不知道sendEmail,但我希望它返回我请求的属性。

发电子邮件:

module.exports = (message) =>
    new Promise((resolve, reject) => {
        const data = {
            from: 'mymail@example.com',
            to: message.to,
            subject: message.subject,
            text: message.text
        };

        mailgun.messages().send(data, (error) => {
            if (error) {
                return reject(error);
            }
            return resolve();
        });
    });

可以给比我多一点经验的人...谢谢

这里要修复的几件事。 在回调中返回Promise(或任何其他值)不会执行任何操作,并且这样做不会让您随意链接其他Promises。 取而代之的是,您的诺言会在回调内被触发,而不会等待。

作为一般经验法则,请勿将Promises和回调混在一起。 如果绝对必须使用回调,请始终将回调包装在Promise中(就像在sendMail内部一样)。 幸运的是,当今大多数流行的库都支持回调和Promises。 这是重构上面的代码以正确链接所有Promises的方法:

createDealer(_, params) {
  return bcrypt.hash(params.dealer.password, 10) // note the return here!
    .then(hash => {
      params.dealer.password = hash
      const session = driver.session()
      const query = "CREATE (d:Dealer {email:$dealer.email}) SET d += $dealer RETURN d"
      const here = "here".link("mymail@example.com")
      const messageObj = {
         to: params.dealer.email,
         subject: 'Dealer Registration',
         text: `Thank you for signing up. To complete and activate your registration please click ${here}.`
      }
      return sendEmail(messageObj) // note the return here!
    }).then(data => {
      return session.run(query, params) // note the return here!
    }).then(result => {
      result.records[0].get("d").properties // note the return here!
    })
  • 如果您不传递bcrypt.hash会为您自动生成盐-无需调用两个单独的函数
  • 我们使用bcrypt.hash启动Promise链,因此我们需要返回它返回的Promise。 解析程序必须返回一个值或将解析为一个值的Promise,否则它将返回null。
  • 在每个then内部,我们返回一个Promise。 通过这种方式,我们“链接”了我们的Promises,允许在解析器中返回的最终值成为链中最后一个Promise解析为的值。

我们还需要修复您的sendMail函数以实际返回值。 您正确地在函数内部返回了新的Promise,但是您还需要传递返回的data对象来进行解析。 这告诉Promise解决该价值。

module.exports = (message) => new Promise((resolve, reject) => {
  const data = // ...etc
  mailgun.messages().send(data, (error) => {
    if (error) reject(error) // no need to return, it's pointless
    resolve(data) // pass data to resolve
  })
})

旁注:看起来像官方的mailgun库支持Promises。

此外,我强烈建议您考虑使用异步/等待,尤其是在处理较长的Promise链时。 它不易出错,更易读:

createDealer async (_, params) {
  const hash = await bcrypt.hash(params.dealer.password)
  params.dealer.password = hash
  const session = driver.session()
  const query = "CREATE (d:Dealer {email:$dealer.email}) SET d += $dealer RETURN d"
  const here = "here".link("mymail@example.com")
  const messageObj = {
    to: params.dealer.email,
    subject: 'Dealer Registration',
    text: `Thank you for signing up. To complete and activate your registration please click ${here}.`
  }
  const emailResult = await sendEmail(messageObj)
  const result = await session.run(query, params)
  return result.records[0].get("d").properties // still need to return!
}

编辑:关于捕获错误,GraphQL将捕获您的解析器引发的任何错误,这意味着您经常可以自己跳过使用catch 例如,如果您的mailgun请求失败,它将生成某种错误,并且您的查询将为errors数组内的data和错误详细信息返回null。

这可能就足够了,尽管1)您可能希望将错误的堆栈记录到其他位置; 2)在生产中,您可能不想公开内部错误的详细信息。

这意味着您可能要使用自定义错误。 另外,您可以在错误中添加一些自定义属性,以帮助客户有效地处理它们。 因此,您的代码可能最终看起来像这样:

class DeliveryFailureError extends Error {}
DeliveryFailureError.code = 'DELIVERY_FAILURE'
DeliveryFailureError.message = 'Sorry, we could not deliver the email to your account'

try {
  await mailgun.messages.create()
} catch (err) {
  logger.error('Mailgun request failed:', err.stack)
  throw new DeliveryFailureError()
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM