惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Last Watchdog
The Last Watchdog
C
Cyber Attacks, Cyber Crime and Cyber Security
L
LINUX DO - 热门话题
G
GRAHAM CLULEY
S
Schneier on Security
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
SegmentFault 最新的问题
IT之家
IT之家
阮一峰的网络日志
阮一峰的网络日志
Recorded Future
Recorded Future
I
Intezer
云风的 BLOG
云风的 BLOG
博客园 - Franky
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
T
Tenable Blog
The Hacker News
The Hacker News
T
The Blog of Author Tim Ferriss
Attack and Defense Labs
Attack and Defense Labs
D
DataBreaches.Net
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
N
News and Events Feed by Topic
有赞技术团队
有赞技术团队
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
N
News and Events Feed by Topic
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
S
Secure Thoughts
The Register - Security
The Register - Security
B
Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
The Cloudflare Blog
Webroot Blog
Webroot Blog
W
WeLiveSecurity
H
Heimdal Security Blog
博客园 - 三生石上(FineUI控件)
V
Vulnerabilities – Threatpost
G
Google Developers Blog
O
OpenAI News
V
V2EX
罗磊的独立博客
博客园_首页
N
News | PayPal Newsroom
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
TaoSecurity Blog
TaoSecurity Blog
Cloudbric
Cloudbric
H
Hacker News: Front Page
博客园 - 叶小钗
T
Tor Project blog
AI
AI

博客园 - givebest

Glarity Summary - 利用 ChatGPT为Bilibili及YouTube视频内容生成摘要 (免费无广告) Nodejs CMS——基于 NestJS/NuxtJS 的完整开源项目 Vee-validate 父组件获取子组件表单校验结果 Vue.js + Nuxt.js 项目中使用 Vee-validate 表单校验 又拍云 Node.js 实现文件上传、删除 Docz 用 MDX 写 React UI 组件文档 - givebest Mac 远程连接 Windows - givebest Node.js 上传文件 - givebest - 博客园 win10 系统右键菜单不显示文字(只有小图标)修复方法 JavaScript 排序算法(JavaScript sorting algorithms) JavaScript addEventListener 第三个参数 webpack 实现的多入口项目脚手架 Kindle电子阅读器收不到个人文档推送解决方案 纯CSS3大转盘抽奖(响应式、可配置) - givebest - 博客园 JavaScript简单分页,兼容IE6,~3KB 原生JavaScript实现hasClass、addClass、removeClass、toggleClass - givebest - 博客园 JavaScript闭包(Closure) GitHub Pages 绑定二级域名 - givebest HTML5 Canvas绘制转盘抽奖 - givebest - 博客园
更优雅的方式: JavaScript 中顺序执行异步函数
givebest · 2018-04-05 · via 博客园 - givebest

火于异步

1995年,当时最流行的浏览器——网景中开始运行 JavaScript (最初称为 LiveScript)。 1996年,微软发布了 JScript 兼容 JavaScript。随着网景、微软竞争而不断的技术更新,在 2000年前后,JavaScript 相关的技术基础准备就绪。 随后到 2005 年前后,以 Google 为首开始重视使用 AJAX(即 Asynchronous JavaScript and XML),使得复杂的网页交互体验接近桌面应用。

然后,随着 Web 应用变得越来越复杂 ,JavaScript 的生态和重要性也日益提升,YUI、prototype.js、jQuery 等各种库相应登场,随之而来就到了 JavaScript 的繁荣期。

2008年,Google 发布了 JavaScript 引擎 V8 大大改善了 JavaScript 的执行速度,进一步推动了 JavaScript 的繁荣,也为 JavaScript 进军服务器端打下了基础(如:Node.js)。

顺序执行异步函数

异步为 JavaScript 带来非阻塞等优势的同时,同时也在一些场景下带了不便,如:顺序执行异步函数,下面总结了一些常用的方法。

1. "回调地狱"

随着应用复杂度几何式增加,我们可能遇到下面“回调地狱”式的代码。

// 第一个任务
function task1 (callback) {
  setTimeout(() => {
    console.log('1', '我是第一个任务,必须第一个执行');
    callback && callback(1);
  }, 3000);
}

// 第二个任务
function task2 (callback) {
  setTimeout(() => {
    console.log('2', '我是第二个任务');
    callback && callback(2);
  }, 1000);
}

// 第三个任务
function task3 (callback) {
  setTimeout(() => {
    console.log('3', '我是第三个任务');
    callback && callback(3);
  }, 1000);
}

// 所有任务
function allTasks () {
  task1((cb1) => {
    if (cb1) {
      task2((cb2) => {
        if (cb2) {
          task3((cb3) => {
            if (cb3) {
              // 顺序完成所有任务
            }
          })
        }   
      });
    }
  });
}

allTasks();

/**
 * 3秒后
 * 1 我是第一个任务,必须第一个执行
 * 1秒后
 * 2 第二个任务
 * 1秒后
 * 3 第三个任务
 */

2. Promise

为了避免“回调地狱”带来的复杂性和不易阅读,ES6 推出了 Promise。这次实现起来简单多了,但还存在 Promise 中嵌套多层 Promise 的问题,似乎又回到了类似“回调地狱”的问题上。

new Promise(resolve => {
  setTimeout(() => {
    console.log('1', '我是第一个任务,必须第一个执行');
    resolve(1);
  }, 3000);
}).then((val) => {

  new Promise(resolve => {
    setTimeout(() => {
      console.log('2', '我是第二个任务');
      resolve(2);
    }, 1000);
  }).then(val => {
    setTimeout(() => {
      console.log('3', '我是第三个任务');
    }, 1000); 
  });

});
/**
 * 3秒后
 * 1 我是第一个任务,必须第一个执行
 * 1秒后
 * 2 第二个任务
 * 1秒后
 * 3 第三个任务
 */

3. Await、Async

确保支持,详细见:https://caniuse.com/#search=async

为了更易书写和阅读来实现顺序执行异步函数,ES2017 新增了 awaitasync。这次书写体验非常的棒,就像写同步代码一样完成了顺序执行异步的需求。

/**
 * 第一个任务
 */
function task1 () {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('1', '我是第一个任务,必须第一个执行');
      resolve('done');
    }, 3000);
  });
}

/**
 * 第二个任务
 */
function task2 () {

  return new Promise(resolve => {
    setTimeout(() => {
      console.log('2', '第二个任务');
      resolve('done');
    }, 1000)
  });
}

/**
 * 第三个任务
 */
function task3 () {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('3', '第三个任务');
      reject('error');
    }, 1000);
  });
}

/**
 * 第四个任务
 */
function task4 () {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log('4', '第四个任务');
      resolve('done');
    }, 2000);
  })
}

/**
 * 所有任务
 */
async function allTasks () {
  await task1();
  await task2();
  await task3();
  await task4();
}

// 执行任务
allTasks();

/**
 * 3秒后
 * 1 我是第一个任务,必须第一个执行
 * 1秒后
 * 2 第二个任务
 * 1秒后
 * 3 第三个任务
 * Uncaught (in promise) error
 */
完整案例

基于 Node.js,通过 Await 、Async、Promise 实现的顺序执行异步,爬取豆瓣电影截图并按顺序一张张下载图片。

参考

转载请注明出处: http://blog.givebest.cn/javascript/2018/04/05/javascript-sync.html