किसी एक घटना को बार-बार देखने के बजाय क्वेरी का उपयोग करके मेरे सोशल नेटवर्क ऐप के लिए पोस्ट लाने में तेजी लाएं


98

मेरे पास कुंजियों का एक समूह है जो मेरे सोशल नेटवर्क के लिए ऑब्जेक्ट पोस्ट करता है जैसे / पोस्ट / आईडी / (पोस्ट की जानकारी)

जब मैं observeSingleEventOfType(.Value)विधि का उपयोग करते हुए अपने द्वारा लोड किए गए पोस्ट / पोस्ट / 0 और फिर / पोस्ट / 1 आदि लोड करता हूं ।

मैं lazyTableViewएक समय में 30 लोड करने के लिए एक का उपयोग करता हूं और यह काफी धीमा है। क्या कोई तरीका है जिससे मैं क्वेरी विधियों में से किसी एक का उपयोग कर सकता हूं या किसी अन्य तरीके से इसे तेजी से बना सकता हूं, भले ही मुझे अपने एलसन पेड़ में डेटा को फिर से बनाना पड़े।

मैं Parse से अपने ऐप को फिर से लागू कर रहा हूं और अब तक का अनुभव काफी अच्छा रहा है। बस यह एक बात मैं थोड़ा अटका रहा हूं। मदद के लिए अग्रिम धन्यवाद!

संपादित करें:

func loadNext(i: Int) { 

    // check if exhists
    let ideaPostsRef = Firebase(url: "https://APPURL")

    ideaPostsRef.childByAppendingPath(i.description).observeSingleEventOfType(.Value, withBlock: {
        (snapshot) in

        if i % 29 == 0 && i != 0 && !self.hitNull { return }
            // false if nil
            // true if not nil
        if !(snapshot.value is NSNull) {
            let postJSON  = snapshot.value as! [String: AnyObject]
            print("GOT VALID \(postJSON)")
            let post = IdeaPost(message: postJSON["message"] as! String, byUser: postJSON["user"] as! String, withId: i.description)
            post.upvotes = postJSON["upvotes"] as! Int
            self.ideaPostDataSource.append(post)
            self.loadNext(i + 1)
        } else {
            // doesn't exhist
            print("GOT NULL RETURNING AT \(i)")
            self.doneLoading = true
            self.hitNull = true
            return
        }
    }
}

यह पुनरावर्ती कार्य अनिवार्य रूप से फायरबेस से कुंजी संख्या i के लिए मान प्राप्त करता है। यदि यह NSNULL है तो यह पता है कि लोड करने के लिए अंतिम संभव पोस्ट है और फिर कभी नहीं करता है। यदि NSNULL हिट नहीं होता है, लेकिन i % 29 == 0यह आधार मामले के रूप में लौटता है, तो एक समय में केवल 30 पोस्ट लोड किए जाते हैं (0 अनुक्रमित)। जब मैं सेट doneLoadingकरता हूं true, tableView.reloadData()तो एक संपत्ति पर्यवेक्षक का उपयोग करके कहा जाता है।

यहाँ एक नमूना है कि मैं जो सरणी ले रहा हूँ वह कैसा दिखता है

"ideaPosts" : [ {
    "id" : 0,
    "message" : "Test",
    "upvotes" : 1,
    "user" : "Anonymous"
  }, {
    "id" : 1,
    "message" : "Test2",
    "upvotes" : 1,
    "user" : "Anonymous"
  } ]

1
यदि आप हमें इसका वर्णन करने के बजाय अपना कोड दिखाते हैं, तो यह मदद करना बहुत आसान होगा। अपने सवाल में समस्या को पुन: पेश करने के लिए न्यूनतम JSON (पाठ के रूप में, स्क्रीनशॉट नहीं) और कोड शामिल करें और हम देख सकते हैं कि इसे कैसे सुधार किया जा सकता है। MCVE के बारे में और पढ़ें ।
फ्रैंक वैन पफेलन

कोड स्पष्टीकरण शामिल करने के लिए संपादित
Big_Mac

जवाबों:


124

अद्यतन: हम अब इस प्रश्न को AskFirebase प्रकरण में भी शामिल करते हैं ।

Firebase से कई आइटम्स को लोड करना धीमा नहीं पड़ता, क्योंकि आप अनुरोधों को पाइपलाइन कर सकते हैं। लेकिन आपका कोड यह असंभव बना रहा है, जो वास्तव में उप-प्रदर्शन को बढ़ावा देगा।

अपने कोड में, आप सर्वर से एक आइटम का अनुरोध करते हैं, उस आइटम के वापस आने की प्रतीक्षा करें और फिर अगले एक को लोड करें। एक सरल अनुक्रम आरेख में जो दिखता है:

Your app                     Firebase 
                             Database

        -- request item 1 -->
                               S  L
                               e  o
                               r  a
                               v  d
                               e  i
        <-  return item  1 --  r  n
                                  g
        -- request item 2 -->
                               S  L
                               e  o
                               r  a
                               v  d
                               e  i
                               r  n
        <-  return item  2 --     g
        -- request item 3 -->
                 .
                 .
                 .
        -- request item 30-->
                               S  L
                               e  o
                               r  a
                               v  d
                               e  i
                               r  n
                                  g
        <-  return item 30 --

इस परिदृश्य में आप 30 बार अपने राउंडट्रिप टाइम का इंतजार कर रहे हैं + 30 बार डिस्क से डेटा लोड करने में लगने वाला समय। यदि (सादगी के लिए) हम कहते हैं कि राउंडट्रिप्स 1 सेकंड लेते हैं और डिस्क से एक आइटम को लोड करने में एक सेकंड कम से कम 30 * (1 + 1) = 60 सेकंड लगते हैं।

अगर आप एक बार में सभी अनुरोध (या कम से कम उनमें से उचित संख्या) भेजते हैं तो फायरबेस अनुप्रयोगों में आपको बेहतर प्रदर्शन मिलेगा:

Your app                     Firebase 
                             Database

        -- request item 1 -->
        -- request item 2 -->  S  L
        -- request item 3 -->  e  o
                 .             r  a
                 .             v  d
                 .             e  i
        -- request item 30-->  r  n
                                  g
        <-  return item  1 --     
        <-  return item  2 --      
        <-  return item  3 --
                 .
                 .
                 .
        <-  return item 30 --

यदि हम फिर से 1 सेकंड का राउंडट्रिप और लोडिंग का 1 सेकंड मान लेते हैं, तो आप 30 * 1 + 1 = 31 सेकंड का इंतजार कर रहे हैं।

तो: सभी अनुरोध एक ही कनेक्शन के माध्यम से जाते हैं। के बीच है कि, फर्क सिर्फ इतना है को देखते हुए get(1), get(2), get(3)और getAll([1,2,3])फ्रेम के लिए कुछ भूमि के ऊपर है।

मैंने व्यवहार प्रदर्शित करने के लिए एक jsbin स्थापित किया । डेटा मॉडल बहुत सरल है, लेकिन यह अंतर दिखाता है।

function loadVideosSequential(videoIds) {
  if (videoIds.length > 0) {
    db.child('videos').child(videoIds[0]).once('value', snapshot => {
      if (videoIds.length > 1) {
        loadVideosSequential(videoIds.splice(1), callback)
      }
    });
  }
}

function loadVideosParallel(videoIds) {
  Promise.all(
    videoIds.map(id => db.child('videos').child(id).once('value'))
  );
}

तुलना के लिए: क्रमिक रूप से 64 वस्तुओं को लोड करने में मेरे सिस्टम पर 3.8 सेकंड लगते हैं, जबकि उन्हें पाइपलाइन्ड लोड करना (जैसा कि फायरबेस क्लाइंट मूल रूप से करता है) यह 600ms लेता है। सटीक संख्याएं आपके कनेक्शन (विलंबता और बैंडविड्थ) पर निर्भर करेंगी, लेकिन पाइपलाइन्ड संस्करण हमेशा काफी तेज होना चाहिए।


12
अच्छा लगा, पूफ! इसके अलावा, वादे का पालन करना (jQuery.whenAll (), q.all (), या Promise.all ()) यहाँ बहुत उपयोगी हो सकता है यदि आपको सभी वस्तुओं को लोड करने की आवश्यकता है, लेकिन फिर भी कुछ कार्रवाई करने से पहले, उन्हें समानांतर में हथियाना चाहते हैं।
काटो

5
ठंडा। उस के बारे में भी नहीं सोचा था, भले ही मैं इसका इस्तेमाल कर रहा हूं। :-)
फ्रैंक वैन पफ़ेलन

2
@FrankvanPuffelen आप प्रदर्शन के दृष्टिकोण से सही हैं, लेकिन क्या होगा यदि इनमें से कोई भी कॉल किसी भी प्रकार की त्रुटि के कारण वापस नहीं आया? यदि आप इनमें से किसी के भी असफल होने पर बाकी लंबित अनुरोधों को 'रद्द' कर सकते हैं। अनुक्रमिक अनुरोधों के मामले में, हम कोड में जान सकते हैं कि कौन सा अनुरोध विफल हुआ। कृपया अपने विचार साझा करें। धन्यवाद।
पेरी

1
" The Promise.all () विधि [...] पहले वादे के कारण को अस्वीकार करती है।"
Pejalo

4
हम Android में Promise.all कैसे कर सकते हैं? हम Android में सभी डेटा को कैसे लोड कर सकते हैं
मुहम्मद छोटा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.