2015-05-03 18 views
6

Aşağıdaki programı kullanıyorum - asenkronize akış denetimini işlemek için genny.js kullanıyorum - suspend.js ile aynı şeyi denedim - benzer bir hata.Yineleyicim neden tekrar geliştiriliyor?

Stripe nodejs API'sini kullanıyorum.

Yineleyici işlevim iki kez çağrılıyor gibi görünüyor - bu bir hataya neden oluyor - ve neden iki kez çağrıldığını anlamıyorum. Görmediğim basit bir zihin numarası olmalı.

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') 
}) 

konsol çıktısı:

> 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 

Şimdi, aşağıdaki işlevi ile fetchList yerine eğer iyi çalışır:

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

konsol çıktısı:

> node --harmony genny.js 

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

Gerçeği daha fazla göstermek için iterörün next() yöntemi iki kez çağrılır - programın başka bir (çalışmayan) sürümü var.

> node --harmony genny.js 

before run 
Before fetchCharges 
before fetchList 
after fetchList 
callback 
callback 

Bu garip - ve bunu alamadım:

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') 
}) 

Ve bu konsol çıkış burada. Biri benden daha zeki olabilir lütfen açıklayınız.

GÜNCELLEME

Bir geri arama veya yineleyici özgeçmiş fonksiyonu olmadan şerit yöntemleri çağırmak için kod değişti. Ve şimdi çalışıyor. AMA - merakla - "sonuç" da konsola bakın. Ben neden anlamıyorum. Yani şimdi fetchList yineleyici next() fonksiyonu "ikinci kez" diyoruz - ama bir kez bile çağrılır nerede görmüyorum !?

var results = yield stripe.charges.list() 

Güncelleştirilmiş programın tamamı.

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') 
}) 

Bu, karşılaştığınız sorun asenkronisi için iki yaklaşımın bir karışımı kaynaklanıyor

> node --harmony genny.js 

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

'stripe.charges.list' dizininin birden çok kez geri çağırılmadığından emin misiniz? – Bergi

+0

Verim stripe.charges.list (...) 'sonuçlarının gerçekten anlamlı olup olmadığını (yani, bir" veri "dizisi varsa) kontrol edin. – robertklep

+0

Soruyu, kod çağrısı için bir geri arama veya resume() işlevi sağlamadığım bir kodla güncelledim - ve şimdi çalışıyor. Bununla ilgili bir fikrim yok. Kısaca, geri arama işlevi ile şerit çağrısı için bir geri çağırma olarak geçen resume() işlevini yerine koydu ve yalnızca bir kez çağrıldı (belki de bundan sonra yineleyici ilerlemediğim için?) – Joerg

cevap

2

döndürür.

stripe API docs

her kaynak yöntemi son bağımsız değişken olarak, isteğe bağlı bir geri arama kabul bahseder.
Ayrıca, her kaynak yöntemi bir söz verir.Her iki genny ve suspend Düğüm geri arama sözleşmeler ve vaat

burada

Ve ile sorunsuz bir şekilde

işi Ancak

, hatanı yatıyor: çizgide

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

y 'un her ikisini de'u aynı anda kullanın. done(), şeritten geçirilen bir geri arama oluşturur, ancak bu çağrı aynı zamanda verilmiş bir söz verir ve genny/askıya alma, başka bir geri arama kaydettirir. Bu, gözlemlediğiniz Error: callback already called'a yol açar.

Sen sorunu çözmek istiyorum nasıl seçebilir:

  • bir geri arama

    var results = yield stripe.charges.list({}) 
    
  • geçemiyor

    • sözünü

      var results = yield void stripe.charges.list({}, done()) 
      //     ^^^^ 
      
    • verim yok

      (ikincisini öneririm)

    +0

    Tam olarak bu! Detaylı cevabınız için çok teşekkürler. Şimdi hayatımla devam edebilirim. – Joerg