क्या दोनों के बीच कोई उल्लेखनीय अंतर है? मुझे रनटाइम और स्टार्टअप प्रदर्शन से लेकर सुविधाओं और वर्कफ़्लो अंतर तक किसी भी चीज़ में दिलचस्पी है। दस्तावेज़ीकरण अंतर को समझाने पर खराब काम करता है और जब मुझे एक का दूसरे पर उपयोग करना चाहिए।
दोनों संस्करणों में उदाहरण:
बिल्डस्कीमा
const { graphql, buildSchema } = require('graphql');
const schema = buildSchema(`
type Query {
hello: String
}
`);
const root = { hello: () => 'Hello world!' };
graphql(schema, '{ hello }', root).then((response) => {
console.log(response);
});
ग्राफक्यूएलस्कीमा
const { graphql, GraphQLSchema, GraphQLObjectType, GraphQLString } = require('graphql');
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: () => ({
hello: {
type: GraphQLString,
resolve: () => 'Hello world!'
}
})
})
});
graphql(schema, '{ hello }').then((response) => {
console.log(response);
});
1 उत्तर
buildSchema
फ़ंक्शन SDL (स्कीमा परिभाषा भाषा) में एक स्कीमा लेता है और एक GraphQLSchema
ऑब्जेक्ट देता है। प्रत्येक विधि से उत्पन्न दो समान स्कीमा को देखते हुए, रनटाइम प्रदर्शन समान होगा। buildSchema
का उपयोग करने वाले सर्वर के लिए स्टार्टअप समय धीमा होगा क्योंकि एसडीएल को पार्स करने से एक अतिरिक्त चरण जुड़ जाता है जो अन्यथा मौजूद नहीं होगा - क्या कोई ध्यान देने योग्य अंतर होगा, मैं निश्चित रूप से नहीं कह सकता .
buildSchema
का उपयोग करना आमतौर पर अनुचित है, क्योंकि यह आपके स्कीमा की कार्यक्षमता को गंभीर रूप से सीमित कर देता है।
buildSchema
का उपयोग करके जेनरेट किया गया एक स्कीमा:
- अलग-अलग क्षेत्रों के लिए समाधान कार्यों को निर्दिष्ट नहीं कर सकता
- प्रकारों के लिए या तो
resolveType
याisTypeOf
गुण निर्दिष्ट नहीं कर सकते, जिससेUnions
औरInterfaces
का उपयोग करना असंभव हो जाता है - कस्टम स्केलर का उपयोग नहीं कर सकते
आइटम #1 पर पर्याप्त जोर नहीं दिया जा सकता -- buildSchema
आपको अपने स्कीमा में किसी भी फ़ील्ड के लिए रिज़ॉल्वर फ़ंक्शन निर्दिष्ट करने की अनुमति नहीं देता है। इसमें आपके Query
और Mutation
प्रकार के फ़ील्ड शामिल हैं। उदाहरण जो buildSchema
का उपयोग करते हैं, ग्राफ़क्यूएल के डिफ़ॉल्ट रिज़ॉल्वर व्यवहार पर भरोसा करके और root
मान में पास करके इस समस्या को हल करते हैं।
डिफ़ॉल्ट रूप से, यदि किसी फ़ील्ड में कोई resolve
फ़ंक्शन निर्दिष्ट नहीं है, तो GraphQL मूल मान (पैरेंट फ़ील्ड के रिज़ॉल्वर द्वारा लौटाया गया) की जांच करेगा और (यह मानते हुए कि यह एक ऑब्जेक्ट है) उस मूल मान पर एक संपत्ति खोजने का प्रयास करेगा जो क्षेत्र के नाम से मेल खाता है। यदि उसे कोई मेल मिलता है, तो वह उस मान के लिए फ़ील्ड को हल करता है। यदि मैच एक फ़ंक्शन होता है, तो यह पहले उस फ़ंक्शन को कॉल करता है और फिर फ़ंक्शन द्वारा दिए गए मान को हल करता है।
ऊपर के उदाहरण में, पहले स्कीमा में hello
फ़ील्ड में रिज़ॉल्वर नहीं है। GraphQL मूल मान को देखता है, जो रूट स्तर फ़ील्ड के लिए रूट मान है जो पास किया जाता है। रूट मान में hello
नामक फ़ील्ड होता है, और यह एक फ़ंक्शन, इसलिए यह फ़ंक्शन को कॉल करता है और फिर फ़ंक्शन द्वारा दिए गए मान को हल करता है। आप केवल hello
गुण को एक फ़ंक्शन के बजाय एक स्ट्रिंग बनाकर समान प्रभाव प्राप्त कर सकते हैं।
उपरोक्त को देखते हुए, प्रश्न में दिए गए दो उदाहरण वास्तव में समान नहीं हैं। इसके बजाय, हमें इसके समकक्ष होने के लिए दूसरी स्कीमा को इस तरह संशोधित करना होगा:
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: () => ({
hello: {
type: GraphQLString,
}
})
})
});
const root = { hello: () => 'Hello world!' };
graphql(schema, '{ hello }', root).then((response) => {
console.log(response);
});
रूट के माध्यम से एक रिज़ॉल्वर में गुजरना एक साफ चाल है, फिर से यह केवल रूट स्तर के क्षेत्रों (जैसे Query
, Mutation
या Subscription
प्रकार के फ़ील्ड) के लिए काम करता है। यदि आप किसी भिन्न प्रकार के फ़ील्ड के लिए रिज़ॉल्वर प्रदान करना चाहते हैं, तो buildSchema
का उपयोग करके ऐसा करने का कोई तरीका नहीं है।
निचली पंक्ति: buildSchema
का उपयोग न करें।
लेकिन मैं SDL का उपयोग करना चाहता था!
और आप अभी भी कर सकते हैं! लेकिन... वेनिला GraphQL.js का उपयोग करके ऐसा न करें। इसके बजाय, यदि आप अपनी स्कीमा उत्पन्न करने के लिए एसडीएल का उपयोग करना चाहते हैं, तो आपको इसके बजाय graphql-tools
' makeExecutableSchema
का उपयोग करना चाहिए या apollo-server
जैसे अधिक संपूर्ण समाधान का उपयोग करना चाहिए, जो makeExecutableSchema
का उपयोग करता है ढकना। makeExecutableSchema
आपको एक अलग resolvers
ऑब्जेक्ट प्रदान करते हुए SDL का उपयोग करके एक स्कीमा को परिभाषित करने की अनुमति देता है। तो आप कर सकते हैं:
const typeDefs = `
type Query {
hello: String
}
`
const resolvers = {
Query: {
hello: () => 'Hello!',
},
}
const schema = makeExecutableSchema({ typeDefs, resolvers })
अंतर यह है कि, buildSchema
के विपरीत, आप अन्य प्रकारों के लिए रिज़ॉल्वर भी प्रदान कर सकते हैं, और यहां तक कि अपने इंटरफेस या यूनियनों के लिए resolveType
गुण भी प्रदान कर सकते हैं।
const resolvers = {
Query: {
animals: () => getAnimalsFromDB(),
}
Animal: {
__resolveType: (obj) => obj.constructor.name
},
Cat: {
owner: (cat) => getOwnerFromDB(cat.ownerId),
}
}
makeExecutableSchema
का उपयोग करके, आप कस्टम स्केलर और स्कीमा निर्देशों को भी लागू कर सकते हैं, विभिन्न प्रकार के स्कीमा सत्यापन नियमों को आसानी से अनुकूलित कर सकते हैं और यहां तक कि कार्यान्वयन प्रकारों को उनके इंटरफेस से रिज़ॉल्वर को इनहेरिट करने की अनुमति भी दे सकते हैं। जबकि GraphQL.js की मूल बातें समझना और GraphQLSchema
कंस्ट्रक्टर का उपयोग करके एक बुनियादी स्कीमा कैसे उत्पन्न करना महत्वपूर्ण है, makeExecutableSchema
एक अधिक पूर्ण और लचीला समाधान है जो कि अधिकांश परियोजनाओं के लिए जाना-पहचाना विकल्प होना चाहिए। . अधिक विवरण के लिए दस्तावेज़ देखें।
अपडेट करें
यदि आप buildSchema
का उपयोग करने पर तुले हुए हैं, तो वास्तव में ES6 कक्षाओं का उपयोग करके गैर-रूट प्रकारों के लिए रिज़ॉल्वर प्रदान करने में असमर्थता को प्राप्त करना संभव है। यह नमूना स्कीमा देखें। यह buildSchema
की अन्य सभी सीमाओं को संबोधित नहीं करता है, लेकिन यह इसे और अधिक स्वादिष्ट बनाता है।
संबंधित सवाल
जुड़े हुए प्रश्न
नए सवाल
graphql
ग्राफकॉल एक एपीआई तकनीक है जिसे आधुनिक वेब अनुप्रयोगों के जटिल, नेस्टेड डेटा निर्भरता का वर्णन करने के लिए डिज़ाइन किया गया है। इसे अक्सर SOAP या REST का विकल्प माना जाता है