2015-05-03 11 views
6

मेरे पास निम्न प्रोग्राम है - मैं एसिंक्रोनस फ्लो कंट्रोल को संभालने के लिए genny.js का उपयोग करता हूं - मैंने suspend.js - इसी तरह की त्रुटि के साथ ऐसा करने की कोशिश की है।मेरा पुनरावर्तक फिर से उन्नत क्यों हो रहा है?

मैं स्ट्रिप नोडजेस एपीआई का उपयोग कर रहा हूं।

मेरा इटरेटर फ़ंक्शन दो बार कहा जाता है - जो एक त्रुटि उत्पन्न कर रहा है - और मुझे समझ में नहीं आता कि इसे दो बार क्यों कहा जाता है। यह एक साधारण मस्तिष्क चाल होना चाहिए जिसे मैं नहीं देख रहा हूं।

var genny = require('genny') 
genny.longStackSupport = true 

var stripe = require("stripe")("sk_live_....") 

fetchCharges = genny.fn(function* (d) { 
    console.log("Before fetchCharges") 
    var charges = yield fetchList(d()) 
    console.log("After fetchCharges - found ", charges.length) 
    return true 
}) 

fetchList = genny.fn(function* (done) { 
    console.log("before fetchList") 
    var results = yield stripe.charges.list({}, done()) 
    console.log("after fetchList") 
    return results.data 
}) 

genny.run(function* (resume) { 
    console.log('before run') 
    yield fetchCharges(resume()) 
    console.log('after run') 
}) 

कंसोल आउटपुट है:

> node --harmony genny.js 

before run 
Before fetchCharges 
before fetchList 
after fetchList 
After fetchCharges - found 10 
after run 
/Volumes/dev/ingest/node_modules/genny/index.js:50 
     else throw e; 
       ^
Error: callback already called 
    at resume (/Volumes/dev/ingest/node_modules/genny/index.js:154:39) 
    at throwAt (/Volumes/dev/ingest/node_modules/genny/index.js:49:30) 
    at resume (/Volumes/dev/ingest/node_modules/genny/index.js:153:28) 
    at tryProcessPending (/Volumes/dev/ingest/node_modules/genny/index.js:41:28) 
    at resume (/Volumes/dev/ingest/node_modules/genny/index.js:164:17) 
    at null._onTimeout (/Volumes/dev/ingest/node_modules/stripe/lib/StripeResource.js:87:34) 
    at Timer.listOnTimeout (timers.js:110:15) 
From generator: 
    at /Volumes/dev/ingest/genny.js:22:26 

अब, अगर मैं निम्नलिखित समारोह के साथ fetchList की जगह यह ठीक काम करता है:

fetchList = genny.fn(function* (done) { 
    console.log('before doTimeout') 
    console.log('1sec break ...') 
    yield setTimeout(done(), 1000); 
    console.log('after doTimeout') 
    return [] 
}) 

कंसोल आउटपुट है:

> node --harmony genny.js 

before run 
Before fetchCharges 
before doTimeout 
1sec break ... 
after doTimeout 
After fetchCharges - found 0 
after run 

तथ्य को और स्पष्ट करने के लिए कि itertor की अगली() विधि को दो बार बुलाया जाता है - मेरे पास प्रोग्राम का एक और (गैर-कामकाजी) संस्करण है।

var genny = require('genny') 
genny.longStackSupport = true 

var stripe = require("stripe")("sk_live_...") 

fetchCharges = genny.fn(function* (d) { 
    console.log("Before fetchCharges") 
    var charges = yield fetchList(function(err, cb) { 
    console.log("callback") 
    }) 
    console.log("After fetchCharges - found ", charges.length) 
    return true 
}) 

fetchList = genny.fn(function* (done) { 
    console.log("before fetchList") 
    var results = yield stripe.charges.list({}, done()) 
    console.log("after fetchList") 
    return results.data 
}) 

genny.run(function* (resume) { 
    console.log('before run') 
    yield fetchCharges(resume()) 
    console.log('after run') 
}) 

और यह है सांत्वना उत्पादन यहाँ है:

> node --harmony genny.js 

before run 
Before fetchCharges 
before fetchList 
after fetchList 
callback 
callback 

यह अजीब है - और मैं इसे नहीं मिलता है। क्या कोई मेरी तुलना में स्पष्ट हो सकता है कृपया समझाओ।

अद्यतन

मैं एक कॉलबैक या इटरेटर को फिर से शुरू समारोह के बिना पट्टी तरीकों कॉल करने के लिए कोड बदल दिया है। और अब यह काम करता है। लेकिन - उत्सुकता से - "परिणाम" पर कंसोल देखें। मुझे क्यों नहीं मिलता है। तो अब यह fetchList iterator के अगले() फ़ंक्शन को "दूसरी बार" नहीं कहता है - लेकिन मुझे नहीं लगता कि इसे एक बार कहां कहा जाता है !?

var results = yield stripe.charges.list() 

यहां अपडेट किया गया पूरा प्रोग्राम है।

var genny = require('genny') 
genny.longStackSupport = true 

var stripe = require("stripe")("sk_live_i6TrEk5lSRM1CmbSZZPsQzKc") 

fetchCharges = genny.fn(function* (d) { 
    console.log(" fetchCharges {") 
    var charges = yield fetchList(d()) 
    console.log(" } fetchCharges - found ", charges.length) 
    return true 
}) 

fetchList = genny.fn(function* (done) { 
    console.log(" fetchList {") 
    var results = yield stripe.charges.list({}, function(err, results) { 
    console.log("results ") 
    }) 
    console.log(" } fetchList") 
    return results.data 
}) 

genny.run(function* (resume) { 
    console.log('Before run {') 
    yield fetchCharges(resume()) 
    console.log('} after run') 
}) 

यह

> node --harmony genny.js 

Before run { 
    fetchCharges { 
    fetchList { 
    } fetchList 
    } fetchCharges - found 10 
} after run 
results 
+0

क्या आप सुनिश्चित हैं कि 'stripe.charges.list' कई बार कॉलबैक नहीं कॉल करता है? – Bergi

+0

जांचें कि 'उपज stripe.charges.list (...)' के परिणाम वास्तव में समझ में आता है (यानी, अगर उनके पास वास्तव में 'डेटा' सरणी है)। – robertklep

+0

मैंने कोड के साथ प्रश्न अपडेट किया है जहां मैं स्ट्राइप कॉल पर कॉलबैक या फिर से शुरू() फ़ंक्शन भी प्रदान नहीं करता - और अब यह काम करता है। हालांकि मैं इसका एहसास नहीं कर सकता। मैंने कॉलबैक फ़ंक्शन के साथ पट्टी कॉल के लिए कॉलबैक के रूप में पास किए गए रेज़्यूमे() फ़ंक्शन को संक्षिप्त रूप से प्रतिस्थापित किया था और इसे केवल एक बार बुलाया गया था (शायद क्योंकि मैंने उसके बाद इटरेटर को अग्रिम नहीं किया था?) – Joerg

उत्तर

2

समस्या आप अनुभव कर रहे asynchrony के लिए दो दृष्टिकोण का एक मिश्रण की वजह से उपजी देता है।

stripe API docs उल्लेख

हर संसाधन विधि पिछले तर्क के रूप में एक वैकल्पिक कॉलबैक स्वीकार करता है।
इसके अतिरिक्त, प्रत्येक संसाधन विधि एक वादा देता है।

हालांकि, दोनों genny और suspend नोड कॉलबैक सम्मेलनों और वादों

और यहाँ के साथ सहजता से कर

काम अपनी गलती निहित है: लाइन में

var results = yield stripe.charges.list({}, done()) 

वाई कहां एक ही समय में दोनों का उपयोग करें। done() एक कॉलबैक बनाता है जो पट्टी को पारित किया जाता है, लेकिन वह कॉल भी एक वादा उत्पन्न करता है जो उत्पन्न होता है, और जेनी/निलंबन उस पर एक और कॉलबैक पंजीकृत करता है। इससे आप देख रहे हैं Error: callback already called की ओर जाता है।

आप चुन सकते हैं कि कैसे आप इस समस्या को ठीक करना चाहते हैं:

  • वादा

    var results = yield void stripe.charges.list({}, done()) 
    //     ^^^^ 
    
  • उपज नहीं है
  • एक कॉलबैक

    var results = yield stripe.charges.list({}) 
    
उत्तीर्ण नहीं होते हैं

(मैं बाद वाले की सिफारिश करता हूं)

+0

यह बिल्कुल है! आपके विस्तृत उत्तर के लिए बहुत बहुत धन्यवाद। मैं अब अपने जीवन के साथ आगे बढ़ सकता हूं। – Joerg

संबंधित मुद्दे