简体   繁体   English

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

[英]my graphql server mutation return null value

I am having challenges retrieving the results of my mutation. 我在检索突变结果时遇到了挑战。 I need to create a db record and send an email notifying to user that the registration was successful. 我需要创建一个数据库记录,并发送一封电子邮件通知用户注册成功。 since both the sending of the email and the db update is server side I want to do both in the same mutation. 因为电子邮件的发送和数据库更新都是服务器端的,所以我想两者都在同一突变中进行。 If the email message fail the db must not be updated. 如果电子邮件失败,则不能更新数据库。 So I have the following Mutation: 所以我有以下突变:

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

Even thought both actions are successful I can't seem to retrieve the results. 甚至以为两个动作都成功了,我似乎无法检索结果。 I get 'undefined' for: console.log('SendMail data....' + JSON.stringify(data)); 我得到以下内容的“未定义”:console.log('SendMail data ....'+ JSON.stringify(data)); while console.log('SendNeo4j data....' + JSON.stringify(result)); 而console.log('SendNeo4j data ....'+ JSON.stringify(result)); does display the correct data 确实显示正确的数据

but graphiql returns 'null' for the mutate. 但graphiql会为突变返回“ null”。 this is the graphiql mutation: 这是graphiql突变:

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

with the DealerInput variables of course. 当然还有DealerInput变量。

I have read where you can retrieve multiple results from a query/mutation but I am not sure how it works. 我已经阅读了可以从查询/变异中检索多个结果的位置,但不确定如何运行。 Here I need both the results of the sendEmail and the db update for my Angular/apollo front-end....I would imaging graphiql knows nothing of the sendEmail but I expected it to return the properties I requested. 在这里,我需要Angular / apollo前端的sendEmail和db update的结果。...我想使graphiql成像不知道sendEmail,但我希望它返回我请求的属性。

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();
        });
    });

Can someone with a little more experience than I help me out here...thanks 可以给比我多一点经验的人...谢谢

Couple of things to fix here. 这里要修复的几件事。 Returning a Promise (or any other value) inside a callback doesn't do anything, and doing so won't let you chain additional Promises like you want. 在回调中返回Promise(或任何其他值)不会执行任何操作,并且这样做不会让您随意链接其他Promises。 Instead, your promise gets fired off inside the callback and isn't awaited. 取而代之的是,您的诺言会在回调内被触发,而不会等待。

As a general rule of thumb, don't mix Promises and callbacks. 作为一般经验法则,请勿将Promises和回调混在一起。 If you absolutely have to use callbacks, always wrap the callback in a Promise (like you did inside sendMail). 如果绝对必须使用回调,请始终将回调包装在Promise中(就像在sendMail内部一样)。 Luckily, most popular libraries today support both callbacks and Promises. 幸运的是,当今大多数流行的库都支持回调和Promises。 Here's how you could refactor the code above to correctly chain all your 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 will autogenerate the salt for you if you don't pass one in -- there's no need to call two separate functions 如果您不传递bcrypt.hash会为您自动生成盐-无需调用两个单独的函数
  • We kick off our Promise chain with bcrypt.hash , so we need to return the Promise it returns. 我们使用bcrypt.hash启动Promise链,因此我们需要返回它返回的Promise。 A resolver must return a value or a Promise that will resolve to a value, otherwise it returns null. 解析程序必须返回一个值或将解析为一个值的Promise,否则它将返回null。
  • Inside each then , we return a Promise. 在每个then内部,我们返回一个Promise。 This way we "chain" our Promises, allowing the final value we return in the resolver to be the value the very last Promise in the chain resolves to. 通过这种方式,我们“链接”了我们的Promises,允许在解析器中返回的最终值成为链中最后一个Promise解析为的值。

We need to also fix your sendMail function to actually return the value. 我们还需要修复您的sendMail函数以实际返回值。 You're correctly returning the new Promise inside the function, but you also need to pass the returned data object to resolve. 您正确地在函数内部返回了新的Promise,但是您还需要传递返回的data对象来进行解析。 That tells the Promise to resolve to that value. 这告诉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
  })
})

Side note: looks like the official mailgun library supports Promises. 旁注:看起来像官方的mailgun库支持Promises。

Additionally, I would strongly encourage you to look into using async/await, especially when dealing with a long Promise chain. 此外,我强烈建议您考虑使用异步/等待,尤其是在处理较长的Promise链时。 It's less error prone and more readable: 它不易出错,更易读:

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!
}

EDIT: With regard to catching errors, GraphQL will catch any errors thrown by your resolver, which means you can often skip using catch yourself. 编辑:关于捕获错误,GraphQL将捕获您的解析器引发的任何错误,这意味着您经常可以自己跳过使用catch For example, if your mailgun request fails, it'll generate some kind of error and your query will return null for data and the error details inside of the errors array. 例如,如果您的mailgun请求失败,它将生成某种错误,并且您的查询将为errors数组内的data和错误详细信息返回null。

That may be sufficient, although 1) you may want to log your error's stack elsewhere; 这可能就足够了,尽管1)您可能希望将错误的堆栈记录到其他位置; and 2) in production, you probably don't want to expose internal error details to the public. 2)在生产中,您可能不想公开内部错误的详细信息。

That means you'll probably want to use custom errors. 这意味着您可能要使用自定义错误。 As a bonus, you can add some custom properties to your errors to help the client deal with them eloquently. 另外,您可以在错误中添加一些自定义属性,以帮助客户有效地处理它们。 So your code may end up looking more like this: 因此,您的代码可能最终看起来像这样:

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.

相关问题 变异令牌一路返回 null Graphql - Mutation token all way return a null Graphql 如何从graphql突变而不是null返回新记录 - how to return new record from graphql mutation instead of null 使用函数生成器将值返回到GraphQL Mutation中的outputFields - Return value to outputFields in GraphQL Mutation using a Function Generator 将输入值传递给我的graphql突变-react / react-apollo - Passing input value to my graphql mutation - react/react-apollo 为什么 graphql 返回“不能返回 null of non-nullable field mutation.createAccnt” - why is graphql returning “cannot return null of non-nullable field mutation.createAccnt” 在 graphql 中更新/编辑用户数据(不能为不可空字段 Mutation.updateUser 返回 null) - Updating/editing user data in graphql(Cannot return null for non-nullable field Mutation.updateUser) GraphQL 错误:无法为不可为空的字段 Mutation.deleteComment 返回 null - GraphQL Error: Cannot return null for non-nullable field Mutation.deleteComment Graphql突变返回null,但数据库已更新 - Graphql mutation returning null, but database is updated 使用 Mutation hook 更新 Graphql 服务器中的数据 - Using Mutation hook to update data in Graphql server 调用graphQL服务器突变到axios url - Calling graphQL server mutation to axios url
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM