构造Javascript的最佳方法如果语句在函数中是同步的

bca*_*001 6 javascript node.js

我问这个问题所以我可以学习用javascript做某事的'最佳实践'方式.说我在这里有这个代码:

var someFunc = function () {
  if (something) {
    // do something
  }
  if (somethingElse) {
    // do somethingElse
  }
};
Run Code Online (Sandbox Code Playgroud)

问题是什么是确保在'somethingElse'之前始终运行'某事'的最佳方法.由于javascript是异步的,我知道我需要某种回调系统来确保这一点.但是,有没有更简单的方法来重构这个?如果有很多if语句怎么办?什么是最好的图书馆干净利落地做这样的事情?提前致谢.

Ale*_*ack 9

并非所有代码行都在Javascript中异步运行.这取决于你的代码.例如:

var someFunc = function () {
  if (something) {
    console.log('something');
  }
  if (somethingElse) {
    console.log('something else');
  }
};
Run Code Online (Sandbox Code Playgroud)

将始终写出以下输出:

something
something else
Run Code Online (Sandbox Code Playgroud)

但是,如果不是打印值,而是调用稍后将运行的函数(如Ajax请求或setTimeout回调),则无法保证代码以正确的顺序运行.此行为取决于您调用的函数.例如,JQuery $.get()函数是异步的(这意味着它将在以后调用您的函数,而不是在您的控件中),如下所示:

var someFunc = function () {
  if (something) {
    $.get('some-file.txt').done(function (result) {
      console.log(result);
    });
  }
  if (somethingElse) {
    $.get('some-other-file.txt').done(function (result) {
      console.log(result);
    });
  }
};
Run Code Online (Sandbox Code Playgroud)

结果输出可以是任何其他输出中的'some-file.txt'和'some-other-file.txt'的内容.

根据经验,每当您将函数传递给另一个函数(回调)时,您可能正在使用Javascript 的异步功能.


嵌套回调

解决此问题的一种方法是在第一个函数中调用第二个异步调用:

var someFunc = function () {
  if (something) {
    $.get('some-file.txt').done(function (result1) {
      console.log(result1);
      if (somethingElse) {
        $.get('some-other-file.txt').done(function (result2) {
          console.log(result2);
        });
      }
    });
  }
};
Run Code Online (Sandbox Code Playgroud)

但是你可能已经猜到了这段代码很难读懂.


承诺救援

使用Promises,您可以拥有更易于阅读的代码.

让我们用promises编写上面丑陋的代码:

var someFunc = function () {
  if (something) {
    $.get('some-file.txt').then(function (result1) {
      console.log(result1);
      if (somethingElse) {
        return $.get('some-other-file.txt');
      }
    }).then(function (result2) {
        console.log(result2);
    });
};
Run Code Online (Sandbox Code Playgroud)

通常,promises使代码更具可读性并避免过多的嵌套回调.你可以链接 promises,它会像同步代码一样读,但它实际上是异步运行的.

请参阅以下问题以获取更多信息:

承诺的收获是什么?

  1. 旧浏览器不支持它们(但您可以使用第三方库添加它们,如ES6 Promise Polyfill.
  2. 在承诺被正式标准化之前,每个库都有自己的实现,这些实现略微不兼容(jQuery,Angular,Ember)
  3. 它们是一个新的学习概念,因此对于新手来说,学习曲线会有点陡峭.