Co e co.envolver comportar-se de forma diferente no nó.js

Apesar de ter descoberto como funcionam os mecanismos de fluxo de Koa, não consigo entender todas as diferenças entre co e co.envolver. Este é o código que está dando o comportamento inesperado:

"use strict";
var co = require("co");

function ValidationError(message, obj, schema) {
    Error.call(this, "Validation failed with message \"" + message + "\".");
    this.name = "ValidationError";
    this.object = obj;
    this.schema = schema;
}

ValidationError.prototype = Object.create(Error.prototype);

function ValidatorWithSchema(properties, schema) {
    this.properties = properties;
    this.schema = schema;
}

ValidatorWithSchema.prototype.validate = function* (obj) {
    var validatedObj = obj;
    for (let schemaKey in this.schema) {
        validatedObj = yield this.properties[schemaKey](validatedObj, this.schema[schemaKey]);
    }
    return validatedObj;
};

var typeGen = function* (obj, type) {
    console.log("Checking against "+ type.name);
    var primitives = new Map([
        [String, "string"],
        [Number, "number"],
        [Boolean, "boolean"]
    ]);
    if (!((obj instanceof type) || (primitives.has(type) && (typeof obj === primitives.get(type))))) {
        var error = new ValidationError("Given object is not of type " + type.name, obj);
        throw error;
    }
    return obj;
};

var validator = new ValidatorWithSchema({type: typeGen}, {type: String});
var runWrap = r => {
    console.log(r);
    console.log("### WRAP ###");
    var validate = co.wrap(validator.validate);
    validate(11).then(console.log, console.error);

};
co(function* () {
    yield validator.validate(11);
}).then(runWrap, runWrap);

a saída para este código é a seguinte:

Checking against String
{ [ValidationError] name: 'ValidationError', object: 11, schema: undefined }
### WRAP ###
11

pode ver que eu embrulhei o uso de co.embrulhar para que seja posterior à simples utilização de co. Agora é evidente que typeGen não está sendo chamado na segunda tentativa, mas por que é este o caso? Não devia ... dois resultados são idênticos?

Author: Michele De Pascalis, 2015-09-21

1 answers

Este é apenas o problema muito comum {[[9]}de chamar métodos "não vinculados" .
Você ainda vai precisar chamar a função embrulhada como um método em sua instância validator. Você pode, por exemplo, usar call na função validate:

var validate = co.wrap(validator.validate);
validate.call(validator, 11).then(console.log, console.error);

Em alternativa, teria de {[6] } o método:

var validate = co.wrap(validator.validate.bind(validator));
validate(11).then(console.log, console.error);

Ou melhor ainda, basta embrulhar a função do gerador no ponto da sua definição, para que o método sempre retorne uma promessa imediatamente:

ValidatorWithSchema.prototype.validate = co.wrap(function* (obj) {
    …
});

…
validator.validate(11).then(console.log, console.error);
 1
Author: Bergi, 2017-05-23 11:51:48