JavaScript基础复习(十一) 异步编程

总是纠结js是异步还是同步?

对于JS 异步还是同步这个问题,不需要纠结太多,在执行DOM渲染时,确实是同步执行的,也是为了安全起见,一步一步执行,如果上一步未完成,下一步是不会运行的。

但本质还是单线程

但是对于 网络请求 这样的场景,一个网络资源啥时候返回,这个时间是不可预估的,所以不能傻傻的等着,也就是这样,设计了异步,不管返回结果,执行后就执行下一步,上一步的执行结果什么时候返回,就什么时候再返回。

实现异步的最核心原理,就是将callback作为参数传递给异步执行函数,当有结果返回之后再触发callback执行

常见的异步操作

  • 网络请求, 如ajax , http.get
  • IO 操作, 如readFile, readdir
  • 定时函数, 如setTimeout, setInterval

网络请求实现发展:

1、回调 2、promise 3、Generator 4、async/await

回调

对于这种传递过去不执行,等出来结果之后再执行的函数,叫做callback,即回调函数,如ajax操作中

使用场景

  • 事件回调
  • Node API
  • setTimeOut/setInterval中的回调函数
  • ajax请求

优点: 简单;

缺点: 不能 try catch; 产生回调地狱

使用

// 比较常见的有ajax
$.ajax('http://www.wyunfei.com/', {
 success (res) {
   // 这里可以监听res返回的数据做回调逻辑的处理
 }
})

// 或者在页面加载完毕后回调
$(function() {
 // 页面结构加载完成,做回调逻辑处理
})

promise

承诺未来会执行,有三种状态,分别是: pedding 未完成, resolved 成功, rejected 失败。

状态改变,只有两种情况

  • pedding -> resolved
  • pedding -> rejected。当promise状态发生改变,就会触发then()里的响应函数处理后续步骤,.then()返回一个新的promise实例,所以可以链式调用

特点

  • 状态一经改变,不会再变化
  • 异步操作可以简化为同步操作,避免层层调用

从表面上看,可以解决回调地狱的问题,但是实际上并没有解决,在使用中,仍然需要有.then()的不断调用

缺点

  • 不能取消promise
  • 不能try catch
  • pedding状态时,不知道现在进展到哪一个阶段

Promise.all([1,2,3]) 可以实现多个异步并行执行,同一时刻获取最终结果的问题,当子Promise全部完成,该Promise完成,返回全部值的数组;当有一个子promise失败,该promise失败,返回第一个失败的结果。

Promise.race() 同上,但只要有一个成功,就返回成功的结果

使用

new Promise(function(resolve, reject) {
    // 一段耗时的一步操作
    resolve('success');
    // reject('fail');
}).then(
    (res)=>{console.log(res)},
    (err)=>{console.log(err)}
)

Generator

generator和函数不同的是,generatorfunction* 定义(注意多出的*号),并且,除了return语句,还可以用yield返回多次;可以在执行过程中多次返回

使用 .next() next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。每一次的next()调用,执行一次yield

使用

function* gen() {
    let a = yield 111;
    console.log(a);
    let b = yield 222;
    console.log(b);
    let c = yield 333;
    console.log(c);
    let d = yield 444;
    console.log(d);
}
let t = gen();
//next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值
t.next(1); //第一次调用next函数时,传递的参数无效
t.next(2); //a输出2;
t.next(3); //b输出3; 
t.next(4); //c输出4;
t.next(5); //d输出5;

try {
    // r1 = yield ajax('http://url-1', data1);
    // r2 = yield ajax('http://url-2', data2);
    // r3 = yield ajax('http://url-3', data3);
    // success(r3);
}
catch (err) {
    // handle(err);
}


async/await

其实就是实现了将 Generator函数和自动执行器(co),包装在一个函数中

基本兼容上面异步方式的 缺点

使用

const fs = require('fs');
const bluebird = require('bluebird');
const readFile = bluebird.promisify(fs.readFile);


async function read() {
    await readFile(A, 'utf-8');
    await readFile(B, 'utf-8');
    await readFile(C, 'utf-8');
    //code
}

read().then((data) => {
    //code
}).catch(err => {
    //code
});

关注我获取更多前端资源和经验分享
在这里插入图片描述

感谢大佬们阅读,希望大家头发浓密,睡眠良好,情绪稳定,早日实现财富自由~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章