资讯专栏INFORMATION COLUMN

JavaScript从初级往高级走系列————异步

andot / 2627人阅读

摘要:之所以是单线程,取决于它的实际使用,例如不可能同添加一个和删除这个,所以它只能是单线程的。所以,这个新标准并没有改变单线程的本质。

</>复制代码

  1. 原文博客地址:https://finget.github.io/2018/05/21/async/
异步

什么是单线程,和异步有什么关系

什么是event-loop

是否用过jQuery的Deferred

Promise的基本使用和原理

介绍一下async/await(和Promise的区别、联系)

异步解决方案

什么是单线程,和异步有什么关系

</>复制代码

  1. 单线程-只有一个线程,只做一件事。JS之所以是单线程,取决于它的实际使用,例如JS不可能同添加一个DOM和删除这个DOM,所以它只能是单线程的。

</>复制代码

  1. console.log(1);
  2. alert(1);
  3. console.log(2);

上面这个例子中,当执行了alert(1),如果用户不点击确定按钮,console.log(2)是不会执行的。

</>复制代码

  1. 为了利用多核CPU的计算能力,HTML5提出WebWorker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。
js异步

</>复制代码

  1. console.log(100);
  2. setTimeout(function(){
  3. console.log(200);
  4. },1000)
  5. console.log(300);
  6. console.log(400);
  7. console.log(400);
  8. .... // 这里来很多很多个console.log(400); 结果就是打印完所有的400,等一秒再打印200
event-loop

文字解释

事件轮询,JS实现异步的具体解决方案

同步代码,直接执行

异步函数先放在异步队列中

待同步函数执行完毕,轮询执行 异步队列 的函数

上面那个例子的执行效果就是这样的:

实例分析:

</>复制代码

  1. 这个例子中有两种情况,取决于ajax的返回时间,如果ajax时间小于100ms它就先放进异步队列
Jquery Deferred Jquery1.5前后的变化

</>复制代码

  1. var ajax = $.ajax({
  2. url: "data.json",
  3. success: function(){
  4. console.log("success1");
  5. console.log("success2");
  6. console.log("success3");
  7. },
  8. error: function(){
  9. console.log("error");
  10. }
  11. })
  12. console.log(ajax); // 返回一个xhr对象

</>复制代码

  1. // 链式操作
  2. var ajax = $.ajax("data.json");
  3. ajax.done(function(){
  4. console.log("success1");
  5. }).fail(function(){
  6. console.log("error");
  7. }).done(function(){
  8. console.log()
  9. })
  10. console.log(ajax); // 返回一个deferred对象

无法改变JS异步和单线程的本质

只能从写法上杜绝callback这种形式

它是一种语法糖形式,但是解耦了代码

很好的体现:开放封闭原则(对扩展开放,对修改封闭)

使用Jquery Deferred

</>复制代码

  1. // 给出一段非常简单的异步操作代码,使用setTimeout函数
  2. var wait = function(){
  3. var task = function(){
  4. console.log("执行完成)
  5. }
  6. setTimeout(task, 2000);
  7. }
  8. wait();

新增需求:要在执行完成之后进行某些特别复杂的操作,代码可能会很多,而且分好几个步骤

</>复制代码

  1. function waitHandle(){
  2. var dtd = $.Deferred(); // 创建一个deferred对象
  3. var wait = function(dtd){ // 要求传入一个deferred对象
  4. var task = function(){
  5. console.log("执行完成");
  6. dtd.resolve(); // 表示异步任务已经完成
  7. // dtd.reject(); // 表示异步任务失败或出错
  8. }
  9. setTimeout(task, 2000);
  10. return dtd; // 要求返回deferred对象
  11. }
  12. // 注意,这里一定要有返回值
  13. return wait(dtd);
  14. }
  15. var w = waitHandle();
  16. w.then(function(){
  17. console.log("ok 1");
  18. }, function(){
  19. console.log("err 1");
  20. }).then(function(){
  21. console.log("ok 2");
  22. }, function(){
  23. console.log("err 2");
  24. })

当执行dtd.reject()时:

</>复制代码

  1. var w = waitHandle();
  2. w.then(function(){
  3. console.log("ok 1");
  4. }, function(){
  5. console.log("err 1");
  6. })
  7. // 不能链式
  8. w.then(function(){
  9. console.log("ok 2");
  10. }, function(){
  11. console.log("err 2");
  12. })

上面封装的waitHandle方法,由于直接返回了dtd(deferred对象),所以用户可以直接调用w.reject()方法,导致无论是成功还是失败,最后都走失败。

</>复制代码

  1. // 修改
  2. function waitHandle(){
  3. var dtd = $.Deferred();
  4. var wait = function(dtd){
  5. var task = function(){
  6. console.log("执行完成");
  7. dtd.resolve();
  8. }
  9. setTimeout(task, 2000);
  10. return dtd.promise(); // 注意这里返回的是promise,而不是直接返回deferred对象
  11. }
  12. return wait(dtd);
  13. }

</>复制代码

  1. ES6的Promise:点这里

</>复制代码

  1. // promise封装一个异步加载图片的方法
  2. function loadImg(src) {
  3. var promise = new Promise(function(resolve,reject){
  4. var img = document.createElement("img");
  5. img.onload = function(){
  6. resolve(img)
  7. }
  8. img.onerror = function(){
  9. reject("图片加载失败")
  10. }
  11. img.src = src;
  12. })
  13. return promise;
  14. }
async/await

</>复制代码

  1. 这是ES7提案中的,现在babel已经开始支持了,koa也是用async/await实现的。

then 只是将callback拆分了

async/await 是最直接的同步写法

</>复制代码

  1. // 伪代码
  2. const load = async function(){
  3. const result1 = await loadImg(src1);
  4. console.log(result1);
  5. const result2 = await loadImg(src2);
  6. console.log(result2);
  7. }
  8. load();
最后

创建了一个前端学习交流群,感兴趣的朋友,一起来嗨呀!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/99515.html

相关文章

  • JavaScript初级高级系列————prototype

    摘要:原文博客地址另一篇转载的从初级往高级走系列原型定义原型是对象的一个属性,它定义了构造函数制造出的对象的公共祖先。 原文博客地址:https://finget.github.io/2018/09/13/proto/另一篇转载的JavaScript从初级往高级走系列————prototype 原型 定义: 原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通...

    SKYZACK 评论0 收藏0
  • JavaScript初级高级系列————MVVM-Vue

    摘要:原文博客地址如何理解如何实现是否解读过的源码与框架的区别实现实现独立初始化实例两者的区别数据和视图的分离,解耦开放封闭原则,对扩展开放,对修改封闭在中在代码中操作视图和数据,混在一块了以数据驱动视图,只关心数据变化, 原文博客地址:https://finget.github.io/2018/05/31/mvvm-vue/ MVVM 如何理解 MVVM 如何实现 MVVM 是否解读过 ...

    codercao 评论0 收藏0
  • JavaScript初级高级系列————Virtual Dom

    摘要:当中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如。则就叫称为重绘。 原文博客地址:https://finget.github.io/2018/05/22/virtualDom/ 什么是虚拟DOM 用JS模拟DOM结构 DOM变化的对比,放在JS层来做(图灵完备语言) 提高重绘性能 重绘和回流 页面渲染过程:showImg(https://seg...

    tinyq 评论0 收藏0
  • JavaScript初级高级系列————ES6

    摘要:采用二八定律,主要涉及常用且重要的部分。对象是当前模块的导出对象,用于导出模块公有方法和属性。箭头函数函数箭头函数把去掉,在与之间加上当我们使用箭头函数时,函数体内的对象,就是定义时所在的对象,而不是使用时所在的对象。 ES6 原文博客地址:https://finget.github.io/2018/05/10/javascript-es6/ 现在基本上开发中都在使用ES6,浏览器环境...

    孙淑建 评论0 收藏0
  • javascript知识点

    摘要:模块化是随着前端技术的发展,前端代码爆炸式增长后,工程化所采取的必然措施。目前模块化的思想分为和。特别指出,事件不等同于异步,回调也不等同于异步。将会讨论安全的类型检测惰性载入函数冻结对象定时器等话题。 Vue.js 前后端同构方案之准备篇——代码优化 目前 Vue.js 的火爆不亚于当初的 React,本人对写代码有洁癖,代码也是艺术。此篇是准备篇,工欲善其事,必先利其器。我们先在代...

    Karrdy 评论0 收藏0

发表评论

0条评论

andot

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<