Ich habe das folgende Programm - Ich benutze genny.js, um die asynchrone Ablaufsteuerung zu behandeln - Ich habe das gleiche mit suspend.js - ähnlicher Fehler versucht.Warum wird mein Iterator wieder vorgerückt?
Ich verwende die Stripe nodejs API.
Meine Iterator-Funktion scheint zweimal aufgerufen zu werden - was einen Fehler verursacht - und ich verstehe nicht, warum sie zweimal aufgerufen wird. Es muss ein einfacher Geistestrick sein, den ich nicht sehe.
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')
})
Die Konsolenausgabe ist:
> 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
Nun, wenn ich fetchList mit der folgenden Funktion ersetzen, es funktioniert:
fetchList = genny.fn(function* (done) {
console.log('before doTimeout')
console.log('1sec break ...')
yield setTimeout(done(), 1000);
console.log('after doTimeout')
return []
})
Die Konsolenausgabe ist:
> node --harmony genny.js
before run
Before fetchCharges
before doTimeout
1sec break ...
after doTimeout
After fetchCharges - found 0
after run
Um die Tatsache weiter zu veranschaulichen dass die next() - Methode des itertors zweimal aufgerufen wird - ich habe eine andere (nicht funktionierende) Version des Programms.
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')
})
Und es ist die Konsolenausgabe ist hier:
> node --harmony genny.js
before run
Before fetchCharges
before fetchList
after fetchList
callback
callback
Es ist komisch - und ich verstehe es nicht. Kann jemand, der klüger ist als ich, bitte erklären.
UPDATE
Ich habe den Code geändert, um die Streifen Methoden ohne einen Rückruf oder Iterator Resume-Funktion aufzurufen. Und jetzt funktioniert es. ABER - neugierig - schauen Sie sich die Konsole bei den "Ergebnissen" an. Ich verstehe nicht warum. Jetzt ruft es die next() - Funktion des fetchList-Iterators nicht "ein zweites Mal" auf - aber ich sehe nicht, wo es einmal aufgerufen wird !?
var results = yield stripe.charges.list()
Hier ist das aktualisierte vollständige Programm.
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')
})
Das gibt
> node --harmony genny.js
Before run {
fetchCharges {
fetchList {
} fetchList
} fetchCharges - found 10
} after run
results
Sind Sie sicher, dass 'stripe.charges.list' seinen Rückruf nicht mehrmals aufruft? – Bergi
Überprüfen Sie, ob die Ergebnisse von 'yield stripe.charges.list (...)' tatsächlich sinnvoll sind (dh wenn sie tatsächlich ein 'data' Array haben). – robertklep
Ich habe die Frage mit Code aktualisiert, wo ich nicht einmal eine Callback- oder resume() - Funktion für den Stripe-Aufruf anbiete - und jetzt funktioniert es. Ich kann es aber nicht verstehen. Ich habe kurz die resume() -Funktion, die ich als Callback an den Stripe-Aufruf mit einer Callback-Funktion übergebe und die nur einmal aufgerufen wurde (vielleicht weil ich den Iterator danach nicht weiterentwickelt habe), ersetzen. – Joerg