Javascript转换异步和同步

时间:2014-04-07 12:07:19

标签: javascript synchronous legacy

我是网络开发的新手。来自Delphi / pascal。我的长期目标是将遗留应用程序转换为Web环境。 (我正在使用此应用程序:http://smartmobilestudio.com/将pascal交叉编译为javascript,但这不应该影响这个问题)。我的旧程序使用同步远程过程调用(RPC' s)到服务器。我使用名为EWD.js(http://robtweed.wordpress.com/2014/01/23/ewd-js-on-fhir/comment-page-1/)的技术,通过node.js进行异步调用。我在这里读了很多关于同步和同步调用的帖子。如果我不能让EWD以同步的方式行事,我担心我只是运气不好。但我想更好地理解这一点。

考虑这个伪代码:

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

如果任何RPC调用失败,则整个应用程序应该失败。我已经阅读了" continuation样式"中的编码,我认为每个异步调用都会告诉在完成后通过onMessage处理程序在收到返回消息时调用回调函数来获取补丁:

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

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

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

这是可能的,虽然尴尬/丑陋。但是这样的情况呢?

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

我没有真实地看到如何将上述内容转换为延续风格。如果在逻辑树或循环中间有一个调用,我怎么能跳回到那个状态?以前怎么做过的?完全重新编码遗留应用程序是不现实的。它非常庞大而复杂。

任何帮助将不胜感激。 感谢

3 个答案:

答案 0 :(得分:3)

你可能想要使用AJAX和jQuery。有一个参数可以确保它发送同步调用而不是正常的异步调用。

它看起来像这样:

if(/*condition*/) {

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

如果你真的不想使用AJAX,并使用nodejs,你可以这样做:

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) {
    ...
  })

如果您需要传递范围,可以执行以下操作。

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

我希望这会有所帮助。

答案 1 :(得分:2)

正如tik27已经说过,最常见的解决方案是使用延迟对象。

您可以从某些框架/库中获取它们或编写自己的框架/库。 我认为最简单的方法是使用jQuery延迟,你可以找到nodejs的内容 在这里(What nodejs library is most like jQuery's deferreds?)。

简而言之:

  1. 您创建一个共享对象,表示某些状态未知的情况, 但你会以某种方式知道它在未来的某个地方
  2. 您将一些回调附加到此对象: 如果条件得到满足应该调用的那些和那些 如果不满足条件,应该调用
  3. 此共享对象具有发出状态信号的方法,因此 在某些时候,你使用它们来表示条件是否已经满足并且此时已经满足 延迟对象相应地调用附加的回调。
  4. 让我们假设

    • 我们有一个“Deferred()”延迟对象构造函数,
    • 延迟对象有方法“完成”,附加一个回调,如果满足条件将被调用
    • 延迟对象有方法“失败”,它附加一个回调函数,如果 条件不符合
    • 延迟对象具有方法“解决”,表示已满足条件
    • 延迟对象有方法“拒绝”,表示没有满足条件
    • 传递给“resolve”的参数将传播到“done”-callbacks
    • 传递给“reject”的参数将传播到“fail”-callbacks

    然后解决方案看起来像这样:

    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
       }
    });
    

    使用大多数现有延迟对象中的方法链接 您可以使这些代码看起来几乎像是同步的。

答案 2 :(得分:1)

我希望我理解你:

你有一个weblient与ewdRESTServer交谈, ewdRESTServer正在与EWDServer交谈, EWDServer正在与你的遗留后端交谈? 你想从你的EWDServer到你的传统后端进行一系列rpc调用吗?

你应该像async.js这样的lib,你可以传递一个错误处理函数作为参数

看看: How to Handle Errors in Node.js using Express