Ricerca…


Elaborazione di query a esecuzione prolungata con nodo

Poiché il nodo è a thread singolo, è necessario risolvere il problema in caso di calcoli a lunga esecuzione.

Nota: questo è l'esempio "pronto per l'esecuzione". Solo, non dimenticare di ottenere jQuery e installare i moduli richiesti.

Logica principale di questo esempio:

  1. Il cliente invia una richiesta al server.
  2. Il server avvia la routine in un'istanza del nodo separato e invia una risposta immediata con l'ID dell'attività correlata.
  3. Il cliente invia continuamente assegni a un server per gli aggiornamenti di stato dell'ID attività specificato.

Struttura del progetto:

    project
    │   package.json
    │   index.html    
    │
    ├───js
    │      main.js
    │      jquery-1.12.0.min.js
    │   
    └───srv
        │    app.js
        ├─── models
        │      task.js
        └─── tasks
               data-processor.js

app.js:

var express     = require('express');
var app         = express();
var http        = require('http').Server(app);
var mongoose    = require('mongoose');
var bodyParser  = require('body-parser');

var childProcess= require('child_process');

var Task        = require('./models/task');

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use(express.static(__dirname + '/../'));

app.get('/', function(request, response){
    response.render('index.html');
});

//route for the request itself
app.post('/long-running-request', function(request, response){
    //create new task item for status tracking
    var t = new Task({ status: 'Starting ...' });
    
    t.save(function(err, task){
        //create new instance of node for running separate task in another thread
        taskProcessor = childProcess.fork('./srv/tasks/data-processor.js');

        //process the messages comming from the task processor
        taskProcessor.on('message', function(msg){
            task.status = msg.status;
            task.save();
        }.bind(this));

        //remove previously openned node instance when we finished
        taskProcessor.on('close', function(msg){
            this.kill();
        });

        //send some params to our separate task
        var params = {
            message: 'Hello from main thread'
        };

        taskProcessor.send(params);
        response.status(200).json(task);
    });
});

//route to check is the request is finished the calculations
app.post('/is-ready', function(request, response){
    Task
        .findById(request.body.id)
        .exec(function(err, task){
            response.status(200).json(task);
        });
});

mongoose.connect('mongodb://localhost/test');
http.listen('1234');

task.js:

var mongoose    = require('mongoose');

var taskSchema = mongoose.Schema({
    status: {
        type: String
    }
});

mongoose.model('Task', taskSchema);

module.exports  = mongoose.model('Task');

data-processor.js:

process.on('message', function(msg){
    init = function(){
        processData(msg.message);
    }.bind(this)();
    
    function processData(message){
        //send status update to the main app
        process.send({ status: 'We have started processing your data.' });

        //long calculations ..
        setTimeout(function(){
            process.send({ status: 'Done!' });
            
            //notify node, that we are done with this task
            process.disconnect();
        }, 5000);
    }
});

process.on('uncaughtException',function(err){
    console.log("Error happened: " + err.message + "\n" + err.stack + ".\n");
    console.log("Gracefully finish the routine.");
});

index.html:

<!DOCTYPE html>
<html>
    <head>
        <script src="./js/jquery-1.12.0.min.js"></script>
        <script src="./js/main.js"></script>
    </head>
    <body>
        <p>Example of processing long-running node requests.</p>
        <button id="go" type="button">Run</button>
        
        <br />
        
        <p>Log:</p>
        <textarea id="log" rows="20" cols="50"></textarea>    
    </body>
</html>

main.js:

$(document).on('ready', function(){
    
    $('#go').on('click', function(e){
        //clear log
        $("#log").val('');
        
        $.post("/long-running-request", {some_params: 'params' })
            .done(function(task){
                $("#log").val( $("#log").val() + '\n' + task.status);
                
                //function for tracking the status of the task
                function updateStatus(){
                    $.post("/is-ready", {id: task._id })
                        .done(function(response){
                            $("#log").val( $("#log").val() + '\n' + response.status);
                            
                            if(response.status != 'Done!'){
                                checkTaskTimeout = setTimeout(updateStatus, 500);
                            }
                        });
                }
                
                //start checking the task
                var checkTaskTimeout = setTimeout(updateStatus, 100);
            });
    });
});

package.json:

{
  "name": "nodeProcessor",
  "dependencies": {
    "body-parser": "^1.15.2",
    "express": "^4.14.0",
    "html": "0.0.10",
    "mongoose": "^4.5.5"
  }
}

Disclaimer: questo esempio ha lo scopo di darti un'idea di base. Per usarlo nell'ambiente di produzione, ha bisogno di miglioramenti.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow