Pergunta

I'm new to web development. Coming from Delphi/pascal. My long term goal is to convert a legacy application to a web environment. (I am using this application: http://smartmobilestudio.com/ to cross compile pascal to javascript, but that shouldn't impact this question). My legacy program uses synchronous remote procedure calls (RPC's) to a server. I am using a technology named EWD.js (http://robtweed.wordpress.com/2014/01/23/ewd-js-on-fhir/comment-page-1/) that makes asynchronous calls via node.js. I have read many many posts here about synchronous vs synchronous calls. And I fear that I am just out of luck if I can't make EWD act in a synchronous fashion. But I want to understand this better.

Consider this pseudocode:

RPCcall
//business logic
RPCCall
//business logic
RPCCall
//business logic.

If any of the RPC calls fail, then the entire application should fail. I have read of coding in a "continuation style", which I take to be that each asynchronous call tells where to pick up the patch upon completion by having the onMessage handler call the callback function upon receipt of return message:

MyProc()
  RPCCall(<name>,MyProc_2);
end;

MyProc2()
  //business logic
  RPCCall(<name, MyProc_3);
end;

MyProc3()
  //business logic
  RPCCall(<name, MyProc_3);
end.

And this would be possible, though awkward / ugly. But what about situations like this?

RPCcall
//business logic
if conditionA then begin
  if conditionA2 then begin
    RPCCall
    //business logic
  end else
    RPCCall
    //business logic
  end else begin
    for i=1 to 10 do begin
      RPCCall
      //business logic
    end;
  end
end

I don't see realistically how to convert the above to continuation style. If there is a call in the middle of a logic tree, or loop, how can I jump back into that state? How has this been done before? It is not realistic to completely recode the legacy application. It is very very large and complex.

Any help will be appreciated. Thanks

Foi útil?

Solução

You might want to use AJAX, along with jQuery. There's a parameter to make sure it sends synchronous calls instead of the normal asynchronous calls.

It would look something like this:

if(/*condition*/) {

function RPCCall() {
    return $.ajax({
        type: "GET",
        url: remote_url,
        async: false
    }).responseText;
}
   //business logic
}

If you really wouldn't want to use AJAX, and use nodejs you could do something like this:

var sequence = Futures.sequence();

sequence
  .then(function(next) {
     http.get({}, next);
  })
  .then(function(next, res) {
     res.on("data", next);
  })
  .then(function(next, d) {
     http.get({}, next);
  })
  .then(function(next, res) {
    ...
  })

If you need to pass along a scope, you could do something like this.

  .then(function(next, d) {
    http.get({}, function(res) {
      next(res, d);
    });
  })
  .then(function(next, res, d) { })
    ...
  })

I hope this will be of some help.

Outras dicas

As tik27 already said most common solution is to use deferred objects.

You can get them from some framework/library or write your own. I think the simplest way would be to use jQuery deferreds, you can find what goes with nodejs here (What nodejs library is most like jQuery's deferreds?).

The idea in short:

  1. You create a shared object which represents some condition with unknown state, but you will somehow know it's state somewhere in the future
  2. You attach some callbacks to this object: those which should be invoked if condition is met and those which should be invoked if condition is not met
  3. This shared object has methods to signal the state of condition, so at some point you use them to signal that condition have been met or not and at this point deferred object invokes attached callbacks accordingly.

Lets assume

  • we have a "Deferred()" deferred object constructor,
  • deferred object has method "done" which attaches a callback which will be invoked if condition is met
  • deferred object has method "fail" which attaches a callback which will be invoked if condition is not met
  • deferred object has method "resolve" which signals that condition have been met
  • deferred object has method "reject" which signals that condition havn't been met
  • the arguments passed to "resolve" are propagated to "done"-callbacks
  • the arguments passed to "reject" are propagated to "fail"-callbacks

then solution could look something like this:

var conditionA = new Deferred();
RPCcall("rpccall1", function (result) {
    //buisness logic that determines state of conditionA
    if(something) {
         conditionA.resolve();
    } else {
         conditionA.reject();
    }
});
conditionA.done( function () {
    // RPCcall for conditionB and following business logic
});
conditionA.fail( function () {
   var conditions = [];
   for( var i = 0; i < 10; i++) {
       conditions[i] = new Deferred();
       // corresponding RPCcall and callbacks setup
       // i hope you get the idea
   }
});

By using method chaining which is present in most existing deferred objects implementations you can make this code look almost like it's synchronous.

I hope that i understand you right:

you have a weblient talking to a ewdRESTServer, the ewdRESTServer is talking to a EWDServer, the EWDServer is talking to your legacy backend? you want to to make a chain of rpc calls from your EWDServer to your legacy backend?

you should you a lib like async.js, you can pass a error handler function as argument

take a look: How to Handle Errors in Node.js using Express

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top