2017-01-02 3 views
0

Frohes neues Jahr!Was gibt es für Bluebird Promise?

Ich wäre sehr dankbar, wenn jemand mir einen Hinweis auf ein Problem mit Bluebird's promisify geben könnte. Es ist ohne weiteres die Situation wie folgt. Ich habe dieses Stück Code:

/** 
* Set up /website endpoint. 
* @param {Object} router A Koa router 
*/ 
module.exports = function(router) { 
/** 
* POST /website 
* 
* Records the activity of following an external 
* website URL. 
*/ 
    router.post('/website', validator, (ctx, next) => co(function *() { 
    var address = forwardedFor(ctx.request, ctx.request.headers); 
    var orgId = /\/?([^\-]+).*/.exec(ctx.request.body.path)[1]; 

    var visit = { 
     websiteUrl: ctx.request.body.url, 
     path: ctx.request.body.path, 
     clientIp: address.ip, 
     userAgent: ctx.request.headers['user-agent'], 
     organization: orgId 
    }; 
    yield tracker.track('website_visit', visit); 
    log.info('Tracked [%s] website visit from client %[email protected]%s%s', visit.websiteUrl, address.ip, orgId, visit.path); 

    ctx.status = 200; 
    ctx.body = { 
     success: true, 
     timestamp: Date.now(), 
     data: visit 
    }; 
    return next(); 
    })()); 
}; 

, die an einem bestimmten Punkt nennt:

/** 
* Register the `event` with the given `name`. 
* @method track 
* @param {String} name The name or type of the event to be saved. 
* @param {Object} event Payload to register as an event. 
* @return {Promise}  A promise on tracking the event. 
*/ 
function track(name, event) { 
    var entity = seneca.make(DEFAULT_BASE, name, event); 
    var save$ = Promise.promisify(entity.save$, { context: entity }); 
    return save$(); 
} 

Dies ruft schließlich:

module.exports = function phonecall() { 
    var seneca = this; 

    seneca.add('cmd:save,role:entity,name:website_visit', function(msg, respond) { 
    var visit = JSON.parse(JSON.stringify(msg.ent.data$(false))); 
    Organization.where('account_no', 'like', `%${visit.organization}%`) 
     .fetch() 
     .then(function(org) { 
     return User 
      .where('id_organization', org.get('id')) 
      .fetch() 
      .then(function(user) { 
      delete visit.organization; 
      var v = new WebsiteVisit(visit); 
      user.websiteVisits().create(v); 
      return user.save(null, { 
       method: 'update' 
      }); 
      }); 
     }) 
     .then((model) => { 
     return { 
      ok: true, 
      model: model 
     }; 
     }) 
     .catch((err) => { 
     return { 
      ok: false, 
      why: err.message || err 
     }; 
     }).asCallback(respond); 
    }); 

    return { 
    name: PLUGIN_NAME 
    }; 
}; 

, die auf einer ganz anderen Anwendung.

Das Hauptproblem ist, dass alles reibungslos läuft und das Modell in die Datenbank eingefügt wird. yield tracker.track('website_visit', visit); dauert jedoch ewig und verhält sich nicht asynchron, wodurch ein Zeitüberschreitungsfehler für die bereits abgeschlossene Funktion ausgelöst wird.

Das ideale Verhalten für yield tracker.track('website_visit', visit); wäre auf einem anderen Thread (asynchron), als ein normaler Versprechen sollte arbeiten, aber als solche nicht ...

vorgesehen

Vielen Dank im Voraus für jede Hilfe handeln.

+0

Versprechen machen Ihren synchronen Code nicht zu asynchronem Code, wenn Sie das denken. – Tomalak

+0

Ich bin mir bewusst, dass Versprechen den Code nicht zu einem asynchronen machen, sondern dieses Verhalten nachahmen, indem es dem Code ermöglicht wird, weiter zu laufen, während er darauf wartet, dass das Versprechen erfüllt wird. – abullrich

+1

Wenn Sie darüber nachdenken, ist das die gleiche Sache wie * "Verwandeln Sie den Code in eine asynchrone" *. Versprechen emulieren nichts. Sie sind eine Abstraktion über Asynchronizität, sie erzeugen keine Asynchronizität. Das muss vorher da sein, in Form von Code, der explizit auf einem anderen Thread läuft und Callbacks aufruft, wenn es fertig ist. Wenn Sie Code haben, der eine Weile dauert und auf demselben Thread ausgeführt wird, ändert das Versprechen diese Tatsache nicht. – Tomalak

Antwort

0

Der Yield-Ausdruck erfordert explizite Anweisungen, um die Ausführung fortzusetzen. Es ist so aufgebaut, dass Sie die Ausführung eines Prozesses stoppen und starten können. In Ihrem Fall scheint dies nicht erforderlich zu sein. Wenn ich mich nicht irre, sieht es so aus, als ob Sie nur auf die Ergebnisse einer asynchronen Funktion warten müssen, bevor Sie fortfahren. Dies ist nur der Standard-Anwendungsfall für ein Versprechen.

Warum nicht einfach dieselbe Promise-Architektur verwenden, die Sie in der phoneCall-Funktion verwenden?

+0

Nun, der ursprüngliche Code wurde von einem anderen Programmierer erstellt, mit dem ich mich in Verbindung setzen möchte (ich habe mir dieselbe Frage gestellt). Aber ich werde es definitiv versuchen. Vielen Dank! – abullrich

Verwandte Themen