Javascript同步异步

JS三座大山


JavaScript是一门单线程的语言,因此,JavaScript在同一个时间只能做一件事,单线程意味着,如果在同个时间有多个任务的话,这些任务就需要进行排队,前一个任务执行完,才会执行下一个任务

JavaScript的单线程,与它的用途是有很大关系,JavaScript是浏览器的脚本语言

// 同步代码
function fun1() {
  console.log(1);
}
function fun2() {
  console.log(2);
}
fun1();
fun2();

// 输出
1
2

表白的案例

同步和异步

因为JavaScript的单线程,因此同个时间只能处理同个任务,所有任务都需要排队,前一个任务执行完,才能继续执行下一个任务,但是,如果前一个任务的执行时间很长,比如文件的读取操作或ajax操作,后一个任务就不得不等着,拿ajax来说,当用户向后台获取大量的数据时,不得不等到所有数据都获取完毕才能进行下一步操作,用户只能在那里干等着,严重影响用户体验

同步任务

同步任务是指在主线程上排队执行的任务,只有前一个任务执行完毕,才能继续执行下一个任务,当我们打开网站时,网站的渲染过程,比如元素的渲染,其实就是一个同步任务

异步任务

异步任务是指不进入主线程,而进入任务队列的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程,当我们打开网站时,像图片的加载,音乐的加载,其实就是一个异步任务

异步

异步(Asynchronous, async)
同步(Synchronous, sync)

function fun1() {
  console.log(1);
}
function fun2() {
  console.log(2);
}
function fun3() {
  console.log(3);
}
fun1();
setTimeout(function(){
  fun2();
},0);
fun3();
 
// 输出

异步机制

  1. 所有同步任务都在主线程上执行,行成一个执行栈
  2. 主线程之外,还存在一个任务队列,只要异步任务有了结果,就会在任务队列中放置一个事件
  3. 一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,看看里面还有哪些事件,那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行
  4. 主线程不断的重复上面的第三步

JS 异步编程进化史

async/await可以说是异步终极解决方案了

异步编程

回调函数(callback)

AJAX。。。
setTimeout

setTimeout(() => {
    task();
},3000)
console.log('执行console');
// 执行console 
// task()
    ⁃   
setTimeout(() => {
    task()
},3000)
sleep(10000000)
    ⁃   
console.log('先执行这里');
setTimeout(() => {
    console.log('执行啦')
},0);
// 先执行这里
// 执行啦

回调不一定是异步

function A(callback){
    console.log("A");
    callback();  //调用该函数
}
function B(){
   console.log("B");
}
A(B);   

回调函数的优点是简单、容易理解和部署

缺点是不利于代码的阅读和维护,各个部分之间高度耦合(Coupling),流程会很混乱,而且每个任务只能指定一个回调函数

Promise

JavaScript处理异步都是以callback的方式,在前端开发领域callback机制几乎深入人心,近几年随着JavaScript开发模式的逐渐成熟,CommonJS规范顺势而生,其中就包括提出了Promise规范,Promise完全改变了js异步编程的写法,让异步编程变得十分的易于理解,同时Promise也已经纳入了ES6,而且高版本的chrome、firefox浏览器都已经原生实现了Promise

优点 缺点
解决回调 无法检查进行状态
链式调用 建立且执行无法取消
减少嵌套 内部错误无法捕捉
  • 一个promise可能有三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected)
  • 一个promise的状态只可能从“等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换
  • promise必须实现then方法(可以说,then就是promise的核心),而且then必须返回一个promise,同一个promise的then可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致
  • then方法接受两个参数,第一个参数是成功时的回调,在promise由“等待”态转换到“完成”态时调用,另一个是失败时的回调,在promise由“等待”态转换到“拒绝”态时调用,同时,then可以接受另一个promise传入,也接受一个“类then”的对象或方法,即thenable对象

new Promise(function (resolve, reject) {
// do …
});

if(typeof(Promise)==="function") {
    console.log("支持");
}
else {
    console.log("不支持");
}
setTimeout(function () {
    console.log("1");
    setTimeout(function () {
        console.log("2");
        setTimeout(function () {
            console.log("3");
        }, 3000);
    }, 4000);
}, 1000);


new Promise(function (resolve, reject) {
    setTimeout(function () {
        console.log("First");
        resolve();
    }, 1000);
}).then(function () {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log("Second");
            resolve();
        }, 4000);
    });
}).then(function () {
    setTimeout(function () {
        console.log("Third");
    }, 3000);
});

格式

new Promise(function (resolve, reject) {
console.log("Run");
});

new Promise(function (resolve, reject) {
    console.log(1);
    resolve(2);
}).then(function (value) {
    console.log(value);
    return 3;
}).then(function (value) {
    console.log(value);
    throw "error";
}).catch(function (err) {
    console.log(err);
});

再来一种写法

let promise = new Promise(function(resolve, reject){
    console.log("1");
    resolve()
});
promise.then(() => console.log("2"));
console.log("3)
console.log("program start....")
function funs(c){
    return new Promise(function(resolve,reject){
        resolve(c+",world");
        
    });
}
funs('hello')
.then(function(retulet){
    console.log(retulet)
})
.then(function(){})
.catch(function(){})
console.log("program end....")


promise copy

var hello = new Promise(function(resolve,reject){
    setTimeout(function(){
     var text = "你好,我是saoge";
     console.log(text);
     resolve(text);
    },1000)
   })
   var say = new Promise(function(resolve,reject){
    setTimeout(function(text){
     console.log(text);
    },1000)
   })

标签

评论