【问题标题】:Javascript coverting asynchronous into synchronousJavascript转换异步和同步
【发布时间】:2014-05-19 16:04:20
【问题描述】:

我是网络开发的新手。来自德尔福/帕斯卡。我的长期目标是将遗留应用程序转换为 Web 环境。 (我正在使用这个应用程序:http://smartmobilestudio.com/ 将 pascal 交叉编译为 javascript,但这不应该影响这个问题)。我的遗留程序对服务器使用同步远程过程调用 (RPC)。我正在使用一种名为 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 调用失败,那么整个应用程序都应该失败。我读过“延续风格”的编码,我认为每个异步调用都会通过让 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

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

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

【问题讨论】:

  • 我会研究 javascript 的延迟/承诺功能,它允许您链接异步调用。
  • 为了一个简单的解决方案,你不能让RPCcall ajax 同步吗?
  • @tik27 -- 我会检查的。谢谢!
  • @Bergi -- 我认为同步调用工作是最好的选择。但是,我需要使用 EWD,因为它连接到我的传统腮腺炎数据库。

标签: javascript synchronous legacy


【解决方案1】:

希望我理解你的正确:

你有一个 webclient 与 ewdRESTServer 对话, ewdRESTServer 正在与 EWDServer 通信, EWDServer 正在与您的旧后端对话? 您想从您的 EWDServer 到您的旧后端进行一系列 rpc 调用吗?

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

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

【讨论】:

  • Rob Tweed 拥有多种不同的 EWD 技术。我不认为我正在使用 ewdRESTserver 的东西。我包含一个连接到 node.js 的 EWD.js 库,它反过来执行可以连接到我的旧 mumps 数据库的服务器端 js。
【解决方案2】:

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

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

简而言之:

  1. 您创建了一个共享对象,它代表了一些未知状态的条件, 但你会以某种方式知道它在未来某个地方的状态
  2. 您将一些回调附加到此对象: 满足条件时应该调用的那些和那些 如果条件不满足,应该调用它
  3. 此共享对象具有指示条件状态的方法,因此 在某些时候,您使用它们来表示条件是否已满足,此时 延迟对象相应地调用附加的回调。

假设

  • 我们有一个“Deferred()”延迟对象构造函数,
  • 延迟对象具有“完成”方法,该方法附加了一个回调,如果满足条件,该回调将被调用
  • 延迟对象具有方法“失败”,该方法附加了一个回调,如果 条件不满足
  • 延迟对象具有方法“resolve”,表明条件已满足
  • 延迟对象具有方法“reject”,表示条件尚未满足
  • 传递给“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
   }
});

通过使用存在于大多数现有延迟对象中的方法链接 你可以让这段代码看起来几乎是同步的。

【讨论】:

  • @Nekiy -- 这是一个经过深思熟虑的回复,我很感激。但是,伙计,这让我头疼。我将拥有超过 100k 行的遗留代码。我无法分离所有逻辑并将其更改为共享对象。但如果我有新的编码,我会记住你的技术。谢谢!
【解决方案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) { })
    ...
  })

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2011-09-07
    • 1970-01-01
    • 2017-12-09
    • 2015-06-25
    • 1970-01-01
    • 1970-01-01
    • 2017-06-29
    • 1970-01-01
    相关资源
    最近更新 更多