javascript - Co 和 co.wrap 在 Node.js 中的行为不同

标签 javascript node.js generator co

虽然我有点弄清楚 Koa 流程机制是如何工作的(我认为),但我似乎无法掌握 co 和 co.wrap 之间的所有差异。这是给出意外行为的代码:

"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);

此代码的输出如下:

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

您可以看到我包装了 co.wrap 的使用,以便它位于简单的 co 使用之后。现在很明显 typeGen 在第二次尝试中没有被调用,但为什么会出现这种情况呢?这两个结果不应该是相同的吗?

最佳答案

这只是很常见的problem of calling "unbound" methods .
您仍然需要将包装的函数作为 validator 实例上的方法进行调用。例如,您可以使用 callvalidate 函数上:

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

或者,您需要 .bind() 方法:

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

或者更好的是,只需将生成器函数包装在其定义点,以便该方法始终立即返回一个 Promise:

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

…
validator.validate(11).then(console.log, console.error);

关于javascript - Co 和 co.wrap 在 Node.js 中的行为不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32684420/

相关文章:

parameters - Keras Sequential fit_generator 参数列表中validation_steps的含义

python - 如何在 Python 3.6 中使用异步生成器?

javascript - 调用 JavaScript 类中的方法

javascript - 从选择多个中获取值

Javascript参数忽略

node.js - 'heroku 日志' 返回 'Response Code 404 (Not Found)'

python - 递归的中间结果

javascript - 你如何在javascript中将纪元转换为可读的日期格式

javascript - 安装与 Node.js 5.0.0 冲突的 NPM 包

javascript - 使用 Node.JS 创建一个无法访问任何以上级别文件的子进程?