2015-09-20 19 views
0

雖然我有點想出了Koa流動機制如何工作(我認爲),但我似乎無法理解co和co.wrap之間的所有差異。這是給意外行爲代碼:Co和co.wrap在Node.js中的行爲有所不同

"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,以便爲它是隨後的簡單合作使用。現在很明顯typeGen在第二次嘗試中沒有被調用,但爲什麼會出現這種情況?這兩個結果不應該完全相同嗎?

+0

我想知道爲什麼'typeGen'是一個生成器?爲什麼你在這裏使用generator + co,似乎沒有任何異步?或者你打算做什麼? – Bergi

+0

上面貼出的代碼是一個扁平模塊/測試對,它複製了令人費解的行爲。 –

+0

是的,令人費解的行爲很容易解釋(請參閱下面的答案),但我認爲'typeGen'應該是一個承諾返回函數而不是生成器返回函數。 – Bergi

回答

1

這只是很常見的problem of calling "unbound" methods
您仍然需要在您的validator實例上將包裝函數作爲方法調用。例如,您可以在validate功能使用call

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

或者更好的,只是包裝發生器功能的點處的定義,以便該方法總是立即返回一個承諾:

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

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

我怎麼看不到它!我昨天剛剛閱讀了這篇文章,但我想我習慣於部分應用實例方法持有它們所屬實例的引用的語言。謝謝! –

相關問題