query {
person(id: "cGVvcGxlOjE=") {
...HomeWorldFragment @defer(label: "homeWorldDefer")
name
films @stream(initialCount: 1, label: "filmsStream") {
title
}
}
}
fragment HomeWorldFragment on Person {
homeWorld {
name
}
}The response to this request will be an incremental stream consisting of an initial incremental stream result followed by one or more incremental stream update result.
The initial incremental stream result has:
- a {"data"} entry containing the results of the GraphQL operation except for
the
@deferand@streamselections; - a {"pending"} entry containing two pending result, one for the
@deferselection and for the the@streamselection, indicating that these results will be delivered in a later incremental stream update result; - a {"hasNext"} entry with the value {true}, indicating that the response is not yet complete.
If an error were to occur, it would also have an {"error"} entry; but not in this example.
{
"data": {
"person": {
"name": "Luke Skywalker",
"films": [{ "title": "A New Hope" }]
}
},
"pending": [
{ "id": "0", "path": ["person"], "label": "homeWorldDefer" },
{ "id": "1", "path": ["person", "films"], "label": "filmsStream" }
],
"hasNext": true
}Depending on the behavior of the backend and the time at which the deferred and streamed resources resolve, the stream may produce results in different orders. In this example, our first incremental stream update result contains the deferred data and the first streamed list item. There is one completed result, indicating that the deferred data has been completely delivered.
{
"incremental": [
{
"id": "0",
"data": { "homeWorld": { "name": "Tatooine" } }
},
{
"id": "1",
"items": [{ "title": "The Empire Strikes Back" }]
}
],
"completed": [
{"id": "0"}
]
"hasNext": true
}The second incremental stream update result contains the final stream results. In this example, the underlying iterator does not close synchronously so {"hasNext"} is set to {true}. If this iterator did close synchronously, {"hasNext"} would be set to {false} and this would be the final incremental stream update result.
{
"incremental": [
{
"id": "1",
"items": [{ "title": "Return of the Jedi" }]
}
],
"hasNext": true
}The third incremental stream update result contains no incremental data.
{"hasNext"} set to {false} indicates the end of the incremental stream. This
incremental stream update result is sent when the underlying iterator of the
films field closes.
{
"hasNext": false
}query {
person(id: "cGVvcGxlOjE=") {
...HomeWorldFragment @defer(label: "homeWorldDefer")
...NameAndHomeWorldFragment @defer(label: "nameAndWorld")
firstName
}
}
fragment HomeWorldFragment on Person {
homeWorld {
name
terrain
}
}
fragment NameAndHomeWorldFragment on Person {
firstName
lastName
homeWorld {
name
}
}In this example the response is an incremental stream of the following results.
The initial incremental stream result contains the results of the firstName
field. Even though it is also present in the HomeWorldFragment, it must be
returned in the initial incremental stream result because it is also defined
outside of any fragments with the @defer directive. Additionally, there are
two pending result indicating that results for both @defers in the query
will be delivered in later incremental stream update result.
{
"data": {
"person": {
"firstName": "Luke"
}
},
"pending": [
{ "id": "0", "path": ["person"], "label": "homeWorldDefer" },
{ "id": "1", "path": ["person"], "label": "nameAndWorld" }
],
"hasNext": true
}In this example, the first incremental stream update result contains the
deferred data from HomeWorldFragment. There is one completed result,
indicating that HomeWorldFragment has been completely delivered. Because the
homeWorld field is present in two separate @defers, it is separated into its
own incremental result.
The second incremental result in this incremental stream update result
contains the data for the terrain field. This incremental result contains a
{"subPath"} entry to indicate to clients that the response position of this
result can be determined by concatenating the path from the pending result
with id "0" and the value of this {"subPath"} entry.
{
"incremental": [
{
"id": "0",
"data": { "homeWorld": { "name": "Tatooine" } }
},
{
"id": "0",
"subPath": ["homeWorld"],
"data": { "terrain": "desert" }
}
],
"completed": [{ "id": "0" }],
"hasNext": true
}The second incremental stream update result contains the remaining data from
the NameAndHomeWorldFragment. lastName is the only remaining field from this
selection that has not been delivered in a previous result. With this field now
delivered, clients are informed that the NameAndHomeWorldFragment has been
completed by the presence of the associated completed result. Additionally,
{"hasNext"} is set to {false} indicating the end of the incremental stream.
{
"incremental": [
{
"id": "1",
"data": { "lastName": "Skywalker" }
}
],
"completed": [{ "id": "1" }],
"hasNext": false
}