4

メールを送信してからデータベースを更新したいとしましょう。両方のアクションは非同期です。普段ならこんな感じで書きます。

send_email(function(err, id){
    if(err){
        console.log("error");
    }else{
        update_database(id,function(err, id){
            if(err){
                console.log("error");
            }else{
                console.log("success");
            }
        });
    }
});

代わりにミドルウェアでこれを行いたいと思います。

var mid = {};

mid.send_email = function(){
    return function(next){
        send_email(function(err,id){
            if(err){
                console.log("error");
            }else{
                next(id);
            }
        });
    }
}

mid.update_database = function(){
    return function(id,next){
        update_database(id,function(err,id){
            if(err){
                console.log("error");
            }else{
                next(id);
            }
        });
    }
}

mid.success = function(){
    return function(id,next){
        console.log("success")
        next(id);
    }   
}

ミドルウェアのスタック。

middleware.use(mid.send_email());
middleware.use(mid.update_database());
middleware.use(mid.success());

手元にある主な質問は 2 つあります。

  • ネストされたコールバックの代わりにミドルウェアを使用するにはどうすればよいですか?
  • に変数を渡すことは可能next()ですか?
4

3 に答える 3

5

必要なのは、非同期制御フローを処理できるようにすることです。多くの js ライブラリがこれを達成するのに役立ちます。実行される次の関数に変数を渡すことができるようにするためAsync、関数を使用してライブラリを試すことができます。waterfall

https://github.com/caolan/async#waterfall

「一連の関数の配列を実行し、それぞれがその結果を配列内の次の関数に渡します。ただし、いずれかの関数がコールバックにエラーを渡すと、次の関数は実行されず、メインのコールバックがすぐに呼び出されてエラーが発生します。 ."

例 :

async.waterfall([
    function(callback){
        callback(null, 'one', 'two');
    },
    function(arg1, arg2, callback){
        callback(null, 'three');
    },
    function(arg1, callback){
        // arg1 now equals 'three'
        callback(null, 'done');
    }
], function (err, result) {
   // result now equals 'done'    
});
于 2013-01-04T02:11:38.390 に答える
1

おそらくCommonJSmodule.exportsを使用したほうがよいでしょう。

次のようなファイルを作成できます。

module.exports = function (){
    function sendEmail(doneCallback){
        // do your stuff, then when you are done:
        if(!err){
            doneCallback(whatever,args,you,need);
        }
    }

    function updateDB(success){
        // do your stuff, then when you are done:
        success(whatever,args,you,need);
    }

    return {
        send: sendEmail,
        update: updateDB
    };
};

次に、あなたのserver.js

var lib = require('./mylib.js');

lib.send(function(result){
   console.log(result);
});

これは似たようなパターンで、私の言いたいことがよくわかるかもしれません。これは、次のように、 a を焼き付けてチェーンする必要がある人に渡すライブラリで構成されていますfunction(より現実的な例、今回はクライアント側):

ui.bistate($('#mybutton'), function(restore){
    $.ajax({
        url: '/api/1.0/catfood',
        type: 'PUT',
        data: {
            catfood: {
                price: 1.23,
                name: 'cheap',
                text: 'Catzy'
            }
        }
    }).done(function(res){
        // stuff with res
        restore();
    });
});

ライブラリでは、次のようrestoreに提供されます。

var ui = function(){
    function bistate(button, action) {
        var originalText = buttonText.data('text'),
            disabledText = buttonText.data('text-disabled');

        function restore(){
            button.prop('disabled', false);
            button.text(originalText);
        }

        function disable(){
            button.prop('disabled', true);
            button.text(disabledText);
        }

        button.on('click', function(){
            disable();
            action(restore);
        });
        restore();
    }

    return {
        bistate: bistate
    };
}();

消費者がボタンを復元したいときにフローを制御できるようにし、消費者がその間に非同期操作を実行したいという複雑なケースをライブラリが処理する必要がないようにします。

一般的に要点は、コールバックを前後に渡すことは巨大であり、十分に広く使用されていないということです。

于 2013-01-04T02:36:43.043 に答える
0

私は仕事でQueue.jsをしばらく使用しています。

于 2013-01-20T03:51:32.243 に答える