node.js - tutorial - ¿Por qué mi iterador está siendo avanzado nuevamente?
npm install (1)
El problema que está experimentando proviene de una combinación de dos enfoques para la asincronía.
La banda API menciona menciones
Cada método de recursos acepta una devolución de llamada opcional como último argumento.
Además, cada método de recursos devuelve una promesa.
Sin embargo, tanto genny como suspender hacen
Trabajar sin problemas con las convenciones y promesas de devolución de llamada de Node
Y aquí yace tu error: en la línea
var results = yield stripe.charges.list({}, done())
usted usa implícitamente ambos al mismo tiempo. El done()
crea una devolución de llamada que se pasa a la banda, pero esa llamada también produce una promesa que se produce, y genny / suspender registrar otra devolución de llamada en él. Esto lleva al Error: callback already called
que está observando.
Puede elegir cómo quiere solucionar el problema:
no cedas la promesa
var results = yield void stripe.charges.list({}, done()) // ^^^^
no pase una devolución de llamada
var results = yield stripe.charges.list({})
(Recomendaría este último)
Tengo el siguiente programa - Yo uso genny.js para manejar el control de flujo asíncrono - He intentado lo mismo con suspend.js - error similar.
Estoy usando la API Stripe nodejs.
La función de mi iterador parece ser llamada dos veces, lo que está causando un error, y no entiendo por qué se llama dos veces. Debe ser un simple truco mental que no estoy viendo.
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'')
})
La salida de la consola es:
> 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
Ahora, si reemplazo fetchList con la siguiente función, funciona bien:
fetchList = genny.fn(function* (done) {
console.log(''before doTimeout'')
console.log(''1sec break ...'')
yield setTimeout(done(), 1000);
console.log(''after doTimeout'')
return []
})
La salida de la consola es:
> node --harmony genny.js
before run
Before fetchCharges
before doTimeout
1sec break ...
after doTimeout
After fetchCharges - found 0
after run
Para ilustrar aún más el hecho de que el método siguiente del (itertor) se llama dos veces, tengo otra versión (no operativa) del programa.
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'')
})
Y la salida de la consola está aquí:
> node --harmony genny.js
before run
Before fetchCharges
before fetchList
after fetchList
callback
callback
Es extraño, y no lo entiendo. ¿Puede alguien más listo que yo? Explique por favor.
ACTUALIZAR
He cambiado el código para llamar a los métodos de banda sin devolución de llamada o la función de reanudación del iterador. Y ahora funciona PERO, curiosamente, mira la consola en los "resultados". No entiendo por qué. Así que ahora no llama a la función next () del repetidor fetchList "por segunda vez", ¡pero no veo dónde se llama una vez!
var results = yield stripe.charges.list()
Aquí está el programa completo actualizado.
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'')
})
Esto regresa
> node --harmony genny.js
Before run {
fetchCharges {
fetchList {
} fetchList
} fetchCharges - found 10
} after run
results