This course has been updated! We now recommend you take the Server-Side GraphQL in Node.js course.

Check out a free preview of the full Introduction to GraphQL course:
The "Resolvers Q&A" Lesson is part of the full, Introduction to GraphQL course featured in this preview video. Here's what you'd learn in this lesson:

Scott answers questions from the audience about clarifications on the last exercise, including how Apollo is processing the schema, extending the current example, and usage of the spread operator in this case.

Get Unlimited Access Now

Transcript from the "Resolvers Q&A" Lesson

[00:00:01]
>> Scott Moss: All right, so if I run a test for that.
>> Speaker 2: So imagine product had notes on it, and for each note they had a created by. So that would no longer be true.
>> Scott Moss: If product had notes on it, like a field called notes?
>> Speaker 2: Yeah, that took maybe an object of note that had a string of the note, and then usually that created it.

[00:00:26] The only reason that you can assume product right there is product is just because that's all you have in the model right now. But the model could get more complicated where created by is more than just, would take more than just a product. Or not?
>> Scott Moss: No, in this case, even if we have more it's always gonna be a product.

[00:00:40] And that's because we're adding this field to the product type. So that means this field is only ever gonna be ran when someone asks to created by field on a product. Which means before this field even executes, this has to be executed at some point first, right? Cuz how else would they have asked for it?

[00:00:56] You couldn't ask for a product type unless you ran a query that had something to do with the product, either directly by writing a query that returns a product or indirectly by writing a query or mutation that returned a type that referenced a product. And even then, it still would get resolved.

[00:01:11] So what I'm saying is there's just no way that this created by field would even be triggered unless the product was already resolved first. See what I mean? And the product's already resolved, then whoever returned it. I mean, I guess technically you could be a jerk and just return a blank object here in one of these queries.

[00:01:29] And this would just be a blank object. But the object still represents a product even though it's a blank object. Mark.
>> Speaker 3: Is there a way to write a resolver that is triggered when an error occurs to delegate to another resolver?
>> Scott Moss: Is there a way to write a resolver that triggers when error returns?

[00:01:50] No, you can't write resolvers to trigger when an error returns. But you can write an error formatter inside the ApolloServer. You can come down here. I got so many things open, let me close some of this stuff. You can come into the server, and they should have a formatError function here that is a function that you can run.

[00:02:17] And so, whenever an error happens on your server, you can grab that error as a first argument, and you can do whatever you want with it. So you can format it, you can change it, you can send it off to your error reporting. You do whatever you want.

[00:02:28] This function's gonna be called every single time there's an error on your server. But you can't write a resolver for it as far as errors go, yeah.
>> Speaker 2: On this resolver that we just did, this created by and product.
>> Scott Moss: Yeah.
>> Speaker 2: There also could be the three other parameters, right?

[00:02:44]
>> Scott Moss: Of course.
>> Speaker 2: You could-
>> Scott Moss: Yeah, they're still there, I'm just not using them, yeah.
>> Speaker 2: But they could be there?
>> Scott Moss: Yeah, so for instance, let's say I went down to right here. Where's created by? Right here. So if I add a arcs here, like I don't know, ID or something like that, yeah, that would show up here.

[00:03:05]
>> Speaker 2: Okay.
>> Scott Moss: Right, so yeah. But again, I can't think of any good example of putting arguments on a field other than if that field had an array. I just can't think of a good one.
>> Scott Moss: Yes.
>> Speaker 2: I did have a question.
>> Scott Moss: What's up, David?
>> Speaker 2: So in the first lesson, we wrote the, what is called, the schema?

[00:03:26] So where is the schema coming from here now?
>> Scott Moss: This is still the same schema. I'm still using the exact same schema. You wrote the scheme. If you checked out, yeah, it's still here. It's just my solution of it. But it's pretty much the same thing that you did.

[00:03:39] It's the exact same thing, I didn't really change it. I might have made one or two changes, but it's the same thing. And that's what the test is looking at. If you look at the test, what I'm actually doing is, as far as the resolvers go, the resolvers don't even know about the schema.

[00:03:53] I'm just running the resolvers purely as far as the test goes, if i go look at product resolvers dot spec. I'm just running them purely. I just literally grab the functions and I run them right here.
>> Speaker 2: I was looking in server.js and the schema.
>> Scott Moss: Yeah, so if you go look in server.js, the schema you created is right here.

[00:04:20] Types, product.
>> Speaker 2: [INAUDIBLE]
>> Scott Moss: Yeah, I'm sorry. The schema that you created is gonna be loaded up by this loads type schema. So this loadTypeSchema takes in a name of a schema, like product, coupon, or user. And it reads it from the file system which is asynchronous, grabs it as a string, merges them all together as one big schema, and then passes it to Apollo.

[00:04:41] So you can see, I'm doing that right here. So I'm taking out an array of schema names, so product, coupon, user. I'm looping over them. I'm loading them individually, which just gives me strings. And then, I save them to this variable here. And then, I just spread them across this array.

[00:05:01] Yeah, so I'm adding them all here combined with the root schema, which is this. So that's where your schema is, it's in here. Yeah, good question.
>> Speaker 2: I have one question, and that is on the update product.
>> Scott Moss: Yes.
>> Speaker 2: Why doesn't args.input get spread whereas in create it gets spread?

[00:05:19]
>> Scott Moss: It's a good question. So the reason it get spread in create is because just in case, one, there's two reasons. One, is simplicity. It's easier for me to write it that way. Two, I want to override or create a possible created by property here to be what this is.

[00:05:34] Cuz that's what this does. The way spread works is whatever's on the right is gonna take precedence over what's on the left. So if there was a created by property here, it's gonna be overridden by whatever I've put here. So that's that. Down here, in update, I don't need to do that.

[00:05:49] I don't need to add an extra argument that's not there. I'm literally just gonna take exactly what's there and input and add it. Up here, I had to because I know for sure, if we go look at new products, let me see.
>> Scott Moss: If we go look at new products in the GraphQL new product input, there is no created by here.

[00:06:09] So I have to add created by. And if I don't do a spread, the only way I can do it is if I maybe try to mutate args.input.createdBy equals, and that's just gross. I don't wanna mutate the argument, so I just made a new object.