Bootstrap

JS异步编程

JavaScript异步编程的四种方法包括回调函数、事件监听、Promise和async/await。
1. 回调函数
回调函数。这是异步编程最基本的方法,适用于处理异步任务。例如,如果有一个耗时的任务f1,可以将其作为回调函数,将另一个函数f2作为参数传入。f1执行完成后,会执行f2,这样就不会堵塞程序的运行,而是先执行主要逻辑,将耗时的操作推迟执行。回调函数的优点是简单、容易理解和部署,但缺点是不利于代码的阅读和维护,因为各个部分之间高度耦合,流程可能会变得混乱,且每个任务只能指定一个回调函数。
假定有两个函数f1和f2,后者等待前者的执行结果。
f1();
f2();
如果f1是一个很耗时的任务,可以考虑改写f1,把f2写成f1的回调函数。

  function f1(callback){
    setTimeout(function () {
      // f1的任务代码
      callback();
    }, 1000);
  }

执行代码就变成下面这样:f1(f2);

采用这种方式,我们把同步操作变成了异步操作,f1不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟执行。

回调函数的优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,流程会很混乱,而且每个任务只能指定一个回调函数。

2.事件监听
另一种思路是采用事件驱动模式。任务的执行不取决于代码的顺序,而取决于某个事件是否发生。还是以f1和f2为例。首先,为f1绑定一个事件。(这里采用的jQuery的写法)。
f1.on('done', f2);
上面这行代码的意思是,当f1发生done事件,就执行f2。然后,对f1进行改写:

function f1(){
     setTimeout(function () {
      // f1的任务代码
      f1.trigger('done');
    }, 1000);
}

f1.trigger('done')表示,执行完成后,立即触发done事件,从而开始执行f2。
这种方法的优点是比较容易理解,可以绑定多个事件,每个事件可以指定多个回调函数,而且可以"去耦合"(Decoupling),有利于实现模块化。缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰。
3. Promises对象
Promise 是ES6新规范,Promise 是js 中异步编程新解决方案。以下简称 Promise为P,
从语法上来说P是一个构造函数,从功能上来说,P 对象用来封装一个异步并获取其成功/失败的结果值。
P 支持链式调用,可以解决回调地狱的问题。回调地狱指的是一个回调函数嵌套着另一个异步任务,不便于阅读,不便于异常处理,
P 的流程是启动异步任务=》返回Promise 对象 =》给promise 对象绑定回调函数。

// 创建一个返回Promise对象的函数
function asyncFunction() {
    return new Promise((resolve, reject) => {
        // 模拟异步操作
        setTimeout(() => {
            const data = '这是从服务器获取到的数据';
            
            if (data) {
                resolve(data); // 成功时调用resolve并传递结果
            } else {
                reject('无法获取数据'); // 失败时调用reject并传递错误信息
            }
        }, 2000);
    });
}
 
// 调用asyncFunction函数并处理其返回的Promise对象
asyncFunction().then((result) => {
    console.log(`成功获取到数据:${result}`);
}).catch((error) => {
    console.error(`发生了错误:${error}`);
});

 在上面的代码中,我们定义了一个名为asyncFunction的函数,该函数返回一个Promise对象。通过将需要进行异步操作的任务放入setTimeout函数内部,我们模拟了一个延迟两秒后才能得到数据的情景。当异步操作完成后,如果有数据则调用resolve方法并传递结果;否则,调用reject方法并传递错误信息。最后,我们通过.then()方法来处理Promise对象的成功状态,并通过.catch()方法来处理Promise对象的失败状态。
4.  async/await 函数的实现
async/await这是ES2017引入的异步编程语法。
JavaScript中的async/await可以用于处理异步操作。下面是使用JavaScript实现async/await异步编程的示例代码:

// 定义一个返回Promise对象的函数
function delay(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
}
 
// 使用async关键字标记该函数为异步函数
async function asyncFunction() {
    // await关键字等待delay函数完成并获取其结果
    const result = await delay(2000);
    
    console.log('Delayed for 2 seconds');
    console.log(`Result: ${result}`);
}
 
// 调用异步函数
asyncFunction();

在上述代码中,我们首先定义了一个名为delay的函数,它接收一个参数表示延时的毫秒数,然后返回一个包装了setTimeout的Promise对象。这样就能模拟一些需要花费时间才能得到结果的异步操作。

接下来,我们通过将async关键字添加到函数前面,将其转换为一个异步函数。在异步函数内部,我们使用await关键字等待delay函数完成并获取其结果。当await语句被执行时,异步函数会立即暂停执行,直到delay函数返回结果或者超时。

最后,我们调用asyncFunction()来开始整个流程。输出结果应该是"Delayed for 2 seconds"和"Result: undefined"(因为delay函数没有返回任何值)。

;