Last active
July 28, 2016 09:28
-
-
Save Globegitter/553f7dffd1f7ceaead1aba0dd56c5554 to your computer and use it in GitHub Desktop.
Hacked defer support
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const defaultNetworkLayer = new Relay.DefaultNetworkLayer(endpoint, { | |
fetchTimeout, | |
retryDelays, | |
headers: {...authHeaders, ...customHeaders} | |
}); | |
defaultNetworkLayer.supports = (...options) => { | |
return options.every(option => { | |
if (option === 'defer') { | |
return true; | |
} | |
return false; | |
}); | |
}; | |
// I am splitting the the requests into ones I found I could execute in parallel and the ones that need to wait on | |
// results. So that would be the ref-queries I suppose. Not sure if checking for it being deferred and it having'request._query.getBatchCall()' | |
// is the best way of doing it, but that seemed to be consistent a consistent way for me. | |
// This code is merely a proof of concept and also wouldn't work for nested ref-queries | |
// Also I noticed that I still got the 'Deferred queries are not supported' invariant, but everything in my test-case got loaded nevertheless. | |
defaultNetworkLayer.sendQueries = (requests) => { | |
var deferredFragmentRequests = []; | |
var nonDeferredRequests = []; | |
requests.forEach(function (request) { | |
if (request._query.isDeferred() && request._query.getBatchCall()) { | |
deferredFragmentRequests.push(request); | |
} else { | |
nonDeferredRequests.push(request) | |
} | |
}); | |
return Promise.all(nonDeferredRequests.map(request => ( | |
defaultNetworkLayer._sendQuery(request).then( | |
result => result.json() | |
).then(payload => { | |
if (payload.hasOwnProperty('errors')) { | |
var error = new Error('Server request for query `' + request.getDebugName() + '` ' + 'failed for the following reasons:\n\n' + formatRequestErrors(request, payload.errors)); | |
error.source = payload; | |
request.reject(error); | |
} else if (!payload.hasOwnProperty('data')) { | |
request.reject(new Error( | |
'Server response was missing for query ' + | |
`\`${request.getDebugName()}\`.` | |
)); | |
} else { | |
deferredFragmentRequests.forEach((deferredFragmentRequest) => { | |
// Match the expected id from the ref query agains the returned request id | |
if (deferredFragmentRequest._query.getBatchCall() && deferredFragmentRequest._query.getBatchCall().sourceQueryID == request.getID()) { | |
const fullPath = deferredFragmentRequest._query.getBatchCall().sourceQueryPath.slice(4).split('.'); | |
let deferredFragmentVariable = payload.data[request._query.getFieldName()]; | |
fullPath.forEach((pathPart) => { | |
deferredFragmentVariable = deferredFragmentVariable[pathPart]; | |
}); | |
// override things in such a way that it this request can be succesfull | |
deferredFragmentRequest._query.__batchCall__ = null; | |
deferredFragmentRequest._query.__identifyingArg__ = { | |
name: "id", | |
value: deferredFragmentVariable, | |
type: "ID!" | |
}; | |
deferredFragmentRequest._query.__calls__ = [{ | |
"name": "id", | |
"value": deferredFragmentVariable, | |
"type": "ID!" | |
}]; | |
deferredFragmentRequest._query.__concreteNode__.fieldName = 'node'; | |
defaultNetworkLayer._sendQuery(deferredFragmentRequest).then(function (result) { | |
return result.json(); | |
}).then(function (payload) { | |
if (payload.hasOwnProperty('errors')) { | |
var error = new Error('Server request for query `' + request.getDebugName() + '` ' + 'failed for the following reasons:\n\n' + formatRequestErrors(request, payload.errors)); | |
error.source = payload; | |
request.reject(error); | |
} else if (!payload.hasOwnProperty('data')) { | |
request.reject(new Error('Server response was missing for query `' + request.getDebugName() + '`.')); | |
} else { | |
request.resolve({response: payload.data}); | |
} | |
})['catch'](function (error) { | |
return request.reject(error); | |
}); | |
} | |
}); | |
request.resolve({response: payload.data}); | |
} | |
}).catch( | |
error => request.reject(error) | |
) | |
))); | |
}; | |
Relay.injectNetworkLayer(defaultNetworkLayer); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment