1

紛らわしいタイトルで申し訳ありませんが、説明を試みます

Express-formとカスタム検証関数でnode.js を次のように使用しています。

app.post('/register', form(
    field("username").trim().required().custom(function(value) {
       //Works correctly
       if (!user.validUsername(value)) {
           throw new error("Invalid username");
       }

       //Does not work due to callback
       user.uniqueUsername(value, function(uniqueUsername) {
            if (!uniqueUsername) {
                //Not unique, throw error
                throw new Error("username is already taken");
                //Could be subsituted for return "whatever"; and it would still be the same problem
            }
        });
    }),
    registerAttempt);
};

// ...
//Example function for brevity  
user.uniqueUsername = function(username, callback) {
    User.findOne({username: username}, function(err, user) {
        if (err) { throw err; }
        callback(user === null);
    });
}

.custom(function(value) { .. }) がコールバックを受け取るまで実行を終了しないように、これを再構築する方法が必要ですが、どうすればそれができるかわかりません。

編集:エラーを修正

4

2 に答える 2

2

Express-form は非同期検証をサポートしていないようです。そのための唯一の方法は、カスタム ミドルウェアを実装することです。次のようになります。

app.post('/register',
    function (req, res, next) { //here it goes
        user.uniqueUsername(req.body.username, function(uniqueUsername) {
            req.body.uniqueUsername = uniqueUsername; //we can't do anything about it yet
            next();
        });    
    },

   form(field('username').trim().required().custom(function(value) {
        if (!user.validUsername(value)) {
             throw new error("Invalid username");
        }   
   }),
   field('uniqueUsername').custom(function(value) {
        if (!value) {
             throw new Error("username is already taken");
        }   
   }),

   registerAttempt);

これは、express-form が非同期検証を行うことができない場合の一般的な回避策として使用できます。必要なすべてのデータを別のミドルウェアにプルし、それを新しいフィールドとして挿入してから、express-form によって検証します。

于 2013-10-12T22:54:54.137 に答える
-1

このような状況では、呼び出しの順序を逆にする必要があります。何かのようなもの:

User.findOne({username: username}, function(err, uniqueUsername) {
    if (err) { throw err; }

    app.post('/register', form(
        field("username").trim().required().custom(function(value) {
            if (!user.validUsername(value)) {
                throw new error("Invalid username");
            }
            if (!(uniqueUsername === null)) {
                //Not unique, throw error
                throw new Error("username is already taken");
            }
        }),
        registerAttempt
    );
};

基本的に、それらを使用する前に値を取得する必要があります (そのように述べた場合、それは明らかなように見えますが、非同期プログラミングでは明らかなことはそれほど明白ではない傾向があります)。

複数の非同期項目をチェックする必要がある場合は、何らかの方法でそれらを連鎖させる必要があります。必要に応じて、非同期ライブラリが役立ちます。

于 2013-10-12T23:55:36.627 に答える