2

仕事用の node.js アプリの開発を開始しましたが、「非同期と考える」ことができません。私の関数では、クエリを実行する必要があり、行ごとに別のクエリを実行して最終結果を計算し、json を作成する必要があります。私はこれをしようとします:

async.series([
    function(callback) {
            db.myCannedResponseList(req.params.websiteid, function(err,questions) {
                if (err) return callback(err);
                ...
                callback();
            });
        },
    function(callback) {
            async.forEachSeries(temp,function(quest,callback) {
                    db.getCannedAnswer(quest.id, function(err,answers) {
                         console.log(answers);
                    });
            }, function(err) {
                if (err) return next(err);
            });
            callback();
        }
    ],
        function(err) { 
            if (err) return next(err);
            res.json(output);
    });

しかし、問題があります: getCannedAnswer の結果はres.json (output)の後に表示されます。どうすれば解決できますか?

4

2 に答える 2

0

非同期関数はネストされているため、コールバックにする必要があります。

アプローチは次のとおりです。

    async.series([
        //async.apply(db.myCannedResponseList,req.params.websiteid), // This is equivalent to the first function below
        //db.myCannedResponseList(req.params.websiteid,callback), // This is equivalent too
        function(callback) {
            db.myCannedResponseList(req.params.websiteid, callback);
        },    
        function(callback) {
            // I'm not sure forEach is the best choice here
            // since it's callback isn't called with all the results so it won't be able to be forwarded...
            // Personally, I use async.times for something like this.
            async.times(temp.length,function(i,next) {
                db.getCannedAnswer(temp[i].id,next);
            },callback)
        }
     ],function(err) { 
          if (err) return next(err);
          res.json(output);
    });

この関数が何async.seriesをすべきかはわかりませんが、エラーが発生した場合は、呼び出すres.json(500,error)res、成功時に呼び出さないでください。

適切なアプローチは、この関数を完全に分離し、完了時に別のコールバックを呼び出すことです。次に、そこに電話resします。

また、配列を渡す代わりにasync.seriesオブジェクトを渡すことができるので、結果は名前空間になります。

完全な例:

    function getCannedStuff(data,callback){
        async.series({
            list : async.apply(db.myCannedResponseList,data.websiteid),
            answer : function(cb) {
                async.times(data.temp.length,function(i,next) {
                db.getCannedAnswer(data.temp[i].id,next);
                },cb)
            }
        },callback);  
    }

次に、別のモジュールから関数を呼び出します。

    getCannedStuff({
        websiteid: req.params.websiteid,
        temp:temp
    },function(error,results) {
        console.log(results.list);
        console.log(results.answer);
        if(err) return res.json(500,{error : error});
        res.json(results)
    });

エラーを内部または外部のどちらで制御するかを決定する必要がありますgetCannedStuffが、それらを渡すのは良いアプローチであり、エラーが発生するかどうかを常に確認するのではありませんif(err)

于 2013-10-20T09:53:25.320 に答える