javascript - वादों का उपयोग करते समय सीरियल लूप से कैसे बाहर निकलना है?



node.js promise (1)

मुझे एक लंबी पाठ फ़ाइल मिल गई है, मैं कुछ घटना डेटा को निकालने और इसे डेटाबेस में संग्रहीत करने के लिए पंक्ति के माध्यम से पंक्ति के माध्यम से लूप को मिलाता हूं। फ़ाइल को समय-समय पर शीर्ष पर नए डेटा के साथ अपडेट किया जाता है। जब ऐसा होता है, तो मैं फाइल के माध्यम से फिर से नई घटनाओं को निकालने में चला जाता हूं, लेकिन जब मैं किसी ऐसे घटना में आना चाहता हूं जो डेटाबेस में पहले से ही है (फ़ाइल को हमेशा सबसे पुराना करने के लिए नवीनतम आदेश दिया गया है)

प्रश्न के इस उत्तर में वर्णित reduce() दृष्टिकोण को reduce() का प्रयोग वादे के लिए छोरों को लिखने का सही तरीका , मैं फ़ाइल को पार्स करने के लिए इस समारोह से आया हूं:

function parse(
    file)
{
    var lines = file.split("\n"),
        latestDate;

    return lines.reduce(function(promise, line) {
        return promise.then(function() {
            if (/* line matches date pattern */) {
                latestDate = line;
            } else if (/* line matches event pattern */) {
                return Event.createAsync(line, latestDate);
            }

            return promise;
        });
    }, Promise.resolve())
        .catch({ errorName: "uniqueViolated" }, 
            function() { /* ignore only the createAsync error */ });
}

createAsync() डेटाबेस पद्धति एक वादा देता है जो इवेंट को createAsync() समय हल किया जाता है। यह एक अपवाद फेंक देगा यदि घटना पहले से डेटाबेस में मौजूद है, जो वादा श्रृंखला को रोक देता है, इसलिए शेष फ़ाइल पार्स नहीं की जाती है फ़ंक्शन के अंत में कैश catch() हेन्डलर द्वारा यह अपवाद पकड़ा गया है और उसे अनदेखा किया गया है। मैं नोड। जेएस में ब्लूबर्ड 3.0 वायर्ड लाइब्रेरी का उपयोग कर रहा हूं।

यह फ़ंक्शन प्रत्येक पंक्ति के माध्यम से लूप क्रमबद्ध और सही ढंग से रोकता है, जब वह पहले ही सहेजी गई घटना को हिट करता है। लेकिन मैं सोच रहा हूं कि वादे के साथ काम करते समय यह लूप से बाहर निकलने का सबसे अच्छा तरीका है। फ़ंक्शन के अंत में फेंक दिया अपवाद को निगलने में थोड़ा सा लगता है।

लूप से निपटने में सुधार के लिए कोई भी सुझाव आपका स्वागत है

उपाय?

जेब के जवाब पर बिल्डिंग, और बर्गी की टिप्पणी को ध्यान में रखते हुए कि शायद मैंने सिर्फ अपने सवाल का जवाब कम-से-कम करने का प्रयास किया, जो मैंने किया था :), मैं इस समाधान के साथ आया था:

function parse(
    file)
{
    var lines = file.split("\n"),
        latestDate;

    return promiseEach(lines, function(line) {
        if (/* line matches date pattern */) {
            latestDate = line;
        } else if (/* line matches event pattern */) {
            return Event.createAsync(line, latestDate);
                .catch({ errorType: "uniqueViolated" }, function() { return false; });
        }
    });
}

लूप पुनरावर्तन को एक जेनेरिक फ़ंक्शन, promiseEach() में स्थानांतरित किया जाता है, जो एक सरणी में प्रत्येक आइटम पर लूप करता है। यदि इटरेटर फ़ंक्शन एक वादा देता है, तो अगले आइटम को तब तक संसाधित नहीं किया जाता जब तक कि वादा का समाधान न हो। यदि इटरेटर false देता false , तो लूप समाप्त होता है, लो-डैश शैली:

function promiseEach(
    list,
    iterator,
    index)
{
    index = index || 0;

    if (list && index < list.length) {
        return Promise.resolve(iterator(list[index])).then(function(result) {
            if (result !== false) {
                return promiseEach(list, iterator, ++index);
            }
        });
    } else {
        return Promise.resolve();
    }
}

मुझे लगता है कि मैं क्या चाहता हूं, लेकिन मैं सोच रहा हूं कि अगर मैं 4000-लाइन फ़ाइल पर कॉल करता हूं तो कॉल स्टैक के मुद्दे होंगे।


जो वास्तव में आप वास्तव में किसी भी लूप से बाहर नहीं निकलते हैं

Event.createAsync लिए हर कॉल एक वादा से तुरंत सफलतापूर्वक लौटाता है, जिसका अर्थ है कि आप हमेशा पूरे सरणी को कम करते हैं।

इस लूप द्वारा उत्पादित वादे-श्रृंखला की लंबाई इसलिए हमेशा फाइल में लाइनों की कुल संख्या होगी, जितनी लाइनों की संख्या, जो न तो आपके विशेष तर्क में तिथि और न ही इवेंट पैटर्न में फिट होती है।

यह इस वायर्ड-चेन का अतुल्यकालिक निष्पादन है जिसे बाद में समाप्त कर दिया गया है जब एक त्रुटि फेंक दी जाती है क्योंकि एक घटना पहले से डेटाबेस में मौजूद है।

आपका कोड काम करता है, लेकिन आपने कहा था कि यह एक लंबी पाठ फ़ाइल थी, इसलिए यह अयोग्य हो सकता है, खासकर यदि प्रारंभ को तोड़ना अपवाद के बजाय आदर्श है (जो आपके वर्णन से लगता है)।

इसलिए मैं इसके बजाय एक पुनरावर्ती दृष्टिकोण पर विचार करेगा:

function parse(file) {
  var latestDate;

  function recurse(lines, i) {
    if (i >= lines.length) return Promise.resolve();

    var line = lines[i];
    if (/* line matches date pattern */) {
      latestDate = line;
    } else if (/* line matches event pattern */) {
      return Event.createAsync(line, latestDate).then(() => recurse(lines, i + 1));
    }
    return recurse(lines, i + 1);
  }

  return recurse(file.split("\n"), 0);
}

पुनरावर्ती दृष्टिकोण का लाभ यह है कि वायदा श्रृंखला को अतुल्यकालिक रूप से बढ़ाया जाता है, जब Event.createAsync निराकरण होता है, और केवल आवश्यकतानुसार। आप केवल रोकने के लिए Event.createAsync को बुला सकते हैं, यानी Event.createAsync लिए कोई ज़रूरत नहीं है Event.createAsync को तोड़ने के लिए एक अपवाद फेंकने के लिए।

अंतर की कल्पना करने का एक तरीका यह हो सकता है कि ट्रेन के लिए पटरियों को बिछाने के लिए तुलना करें, जहां ट्रैक वादा चेन का प्रतिनिधित्व करता है, और रेलगाड़ी ऐसे अतुल्यकालिक कार्यों के निष्पादन का प्रतिनिधित्व करती है जो वादा किए गए हैं:

reduce साथ, ट्रेन को शुरू होने से पहले आप हमेशा पूरे ट्रैक को नीचे रख देते हैं, चाहे कितना दूर ट्रेन ट्रैक को नीचे जा रही है इससे पहले कि अपवाद उसे रोकता है। आप हर बार पूरे ट्रैक को बिछाने की लागत खाती हैं (यह अधिक नहीं हो सकता है, लेकिन यह जोड़ सकते हैं)।

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





bluebird