gpt4 book ai didi

javascript - 我的 graphql 服务器突变返回空值

转载 作者:行者123 更新时间:2023-11-30 11:19:48 27 4
gpt4 key购买 nike

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

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 数据....' + JSON.stringify(data));尽管 console.log('SendNeo4j 数据....' + JSON.stringify(result));确实显示正确的数据

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

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

当然是使用 DealerInput 变量。

我已经阅读过在哪里可以从查询/变更中检索多个结果,但我不确定它是如何工作的。在这里,我需要 sendEmail 的结果和我的 Angular/apollo 前端的数据库更新....我想成像 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(或任何其他值)不会做任何事情,这样做不会让你像你想要的那样链接额外的 Promise。相反,您的 promise 会在回调中被触发并且不会被等待。

根据一般经验,不要混合使用 Promises 和回调。如果您绝对必须使用回调,请始终将回调包装在 Promise 中(就像您在 sendMail 中所做的那样)。幸运的是,当今大多数流行的库都支持回调和 Promises。以下是重构上述代码以正确链接所有 Promise 的方法:

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。通过这种方式,我们“链接”了我们的 Promise,允许我们在解析器中返回的最终值成为链中最后一个 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
})
})

旁注:看起来像 official mailgun library支持 promise 。

此外,我强烈建议您考虑使用 async/await,尤其是在处理长 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 请求失败,它将生成某种错误,并且您的查询将为 dataerrors 数组中的错误详细信息返回 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()
}

关于javascript - 我的 graphql 服务器突变返回空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50223649/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com