链接 JavaScript 函数

chaining javascript functions

本文关键字:函数 JavaScript 链接      更新时间:2023-09-26

我在SO上搜索了一个多小时,找不到像我这样的案例。

我有一个在Ruby on Rails上开发的Web应用程序。它基于具有多个字段和按钮的表单来执行操作。

这些是示例(我的真实应用程序使用更多函数和更多操作组合):当字段 1 被更改时,我想执行 JS 函数 function1(),然后是函数 2(),然后是函数 3()。当 Field2 被更改时,我想执行 JS 函数 function2(),然后执行 function3()。当字段 3 被更改时,我想执行 JS 函数函数 3()。

所有这些 JS 函数调用我的控制器中定义的特定操作,并使用 AJAX 更新表单。我希望 function2() 仅在 function1() 完成表单更新后才开始执行,否则结果将是错误的。

由于这些函数调用的控制器方法将 API 调用发送到许多其他网站,例如 Google 地理编码或 Google 时区,因此它们的响应时间是不可预测的,可能从几 100 毫秒到几秒钟不等。

我试过这个:

onchange="function1();function2();function3()"

但这不起作用,因为 function2() 在 function1() 通过 AJAX 完成更新之前开始执行,并且 function3() 在 function2() 方面也存在同样的问题。

我也试过:

onchange="function1();setTimeout(function(){function2();setTimeout(function(){function3()},FUNCTION2_DELAY)},FUNCTION1_DELAY)"

但这也没有奏效,因为如果FUNCTION1_DELAY设置得太长,function2() 将不会在 FUNCTION1_DELAY 过期之前开始执行,而 function1() 的执行速度可能比 FUNCTION1_DELAY 快得多,如果FUNCTION1_DELAY设置得太短,function2() 将在 function1() 完成 function2() 运行所需的更新之前开始执行。函数 3() 与函数 2() 相同。

我的问题是:有没有更聪明的方法可以让 function2() 仅在 function1() 通过 AJAX 完成表单更新时才开始执行,对于 function3() 对于 function2() 也是如此?我知道我可以创建新的控制器方法,将这些功能合并到其中,例如将 function1()、function2() 和 function3() 合并到 new_function1()、...等中,但这会使我的代码包含重复操作,最终会使它更难维护。所以我宁愿寻找一种更聪明的方法来解决这个问题。

你需要使用Promises。

基本上它的工作原理是这样的:

var MyFunction1 = new Promise(
    function() {
        //do stuff here
    }
);
MyFunction1.then(Myfunction2 ...).then(Myfunction3 ...;

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promisehttp://api.jquery.com/promise/

setTimeout是异步的,所以这不起作用。您可以在函数 1 的末尾调用函数 2,但仍在函数内部。类似地,对于函数 3:

function one(){
  ...logic...
  function two();
}
function two(){
  ...logic...
  function three();
}
function three(){
  ...logic...
}

或者,您可以创建某种函数队列,并且仅在当前函数完成后移动到下一个:

var functionQueue = [
  one,
  two,
  three
];
function next(){
  var nextFn = functionQueue.shift();
  if( nextFn ){
    nextFn();
  }
}
function one(){
  ...logic...
  next();
}
// same for two & three

你也可以使用promises,它非常强大,使代码更清晰易读,但对于这个问题来说可能是矫枉过正的。