一、Javascript的异步原理

  javascript 是单线程语言,所以同一时间只执行一个运算。但有些方法是不能瞬间完成或不可预知何时完成的(如网络请求、settimeout等),为了让它们不对后续的运算产生阻塞,就需要用到异步操作。HTML5提出的Web Worker 允许在后台创建 JavaScript子线程,也可以用来防止阻塞,只是实现方对复杂、浏览器支持性不佳。

  javascript 的异步就是通过回调函数实现的。异步事件被触发时,即意味着对应的回调函数被执行。

  javascript 引擎会基于事件轮询(event-loop)机制捋出一个任务队列:执行所有的同步操作;过程中若遇到异步操作,就将异步事件排入另一个队列;待所有同步操作完成时,开始监听异步事件队列,等待事件触发并执行。

    setTimeout(function() {
console.log("a");    
}, 0); // 这里是异步,0延迟不代表立即执行 var sum=0;
for (var i = 0; i < 1000000; i++) {
sum += i;
};
console.log("b" + sum);

  如上示例,会先打印出b,再打印a。

二、Promise规范

  Promise的目的是为了给异步编程提供统一接口,实现了回调函数的链式写法。目前Promise已经纳入了ES6标准,逐渐成为回调函数的写法规范。

  • 三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected)
  • 一个promise的状态只可能从“等待”转到“完成”态或者“拒绝”态
  • promise必须实现then方法,并接受两个参数,分别是成功和失败后的回调

  Promise规范了Resolve、Reject、Then、Catch、All等方法。 Resolve和Reject分别指代异步操作执行成功和失败时对应执行的回掉函数,它们以参数的形式传入Then方法中。Catch用以捕获错误,All方法可以接收一个元素为 Promise 对象的数组作为参数,当这个数组里面所有的 Promise 对象都变为 resolve 时,该方法才会返回。ES6的Promise基本定义方法如下:

var myPromise = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('执行完成');
resolve('数据传递');
}, 2000);
});
myPromise.then(function(data){
//数据处理代码...
console.log(data);
});

  在创建myPromise的时候,向Promise构造函数传递了两个参数resolve和reject,此时这两个没有实际意义;在执行then的时候,才知道resolve具体是什么函数。上例的then只传了一个函数进来,默认为resolve;若传递了两个函数,则第二个即为reject。myPromise中定义了传给回调函数的数据,上例中“数据传递”即传给了resolve回调函数。

  写入Promise中的异步操作是会立即进入事件队列的,上例中,即使不写myPromise.then(),控制台依旧会打印出“执行完成”。在实际使用中,更科学的控制方式是将Promise对象的定义写入一个函数中,并return这个对象。

function test(){
var myPromise = new Promise(function(resolve, reject){
setTimeout(function(){
console.log('执行完成');
resolve('数据传递');
}, 2000);
});
return myPromise;
}
test().then(function(data){
console.log(data);
});

  then的链式调用能够简化层层回调的写法,避免回调地狱。Promise的精髓是“状态”,用维护状态、传递状态的方式来使得回调函数能够及时调用,它比传递callback函数要简单、灵活的多。在then的resolve方法中返回一个新的Promise对象或者一个数据,都可以后接新的then()。

function test(){
var promise1 = new Promise(function(resolve, reject){
setTimeout(function(){
console.log('第一个Promise执行完成');
resolve('传递给第一个resolve的数据');
}, 2000);
});
return promise1;
}
test().then(function(val){
console.log('进入第一个then');
console.log(val);
var promise2 = new Promise(function(resolve, reject){
setTimeout(function(){
console.log('第一个then执行完成');
resolve('传递给第二个resolve的数据');
}, 2000);
})
return promise2; //返回一个新的Promise对象
}).then(function(val){
console.log('进入第二个then');
console.log(val);
return("传递给第三个resolve的数据") //返回一个值,也可以接then(),其值将被当作参数传递给resolve
}).then(function(val){
console.log("进入第三个then");
console.log(val);
})

  

三、Promise的执行优先级

setTimeout(()=>{
console.log("setTimeout")
},0) new Promise((resolve,reject)=>{
console.log("in promise")
resolve("promise resolve");
}).then((data)=>{
console.log(data)
}) console.log("sync")

  上面代码的执行结果为:先后输出 in promise、sync、promise resolve、setTimeout

  首先要理解,Promise回掉函数的执行是异步的,但Promise本身的定义是同步执行的,所以按照顺序,in promise会在sync前输出。

  其次,Promise回调的优先级是高于setTimeout等异步操作的,所以promise resolve会先于seTtimeout输出。浏览器会将promise callbacks加入到同步事件队列的末尾,而不是异步事件的队列。

js异步原理与 Promise的更多相关文章

  1. JS异步编程 (2) - Promise、Generator、async/await

    JS异步编程 (2) - Promise.Generator.async/await 上篇文章我们讲了下JS异步编程的相关知识,比如什么是异步,为什么要使用异步编程以及在浏览器中JS如何实现异步的.最 ...

  2. js异步原理

    javascript引擎 javascript引擎执行时单线程的,如果有一个任务被阻塞,整个浏览器就会处于假死状态 那么遇到这种情况,又在单线程的情况下,不能像java之类的语言创建多几个线程来处理, ...

  3. 深入理解JS异步编程三(promise)

    jQuery 原本写一个小动画我们可能是这样的 $('.animateEle').animate({ opacity:'.5' }, 4000,function(){ $('.animateEle2' ...

  4. 异步编程之Promise(2):探究原理

    异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2):探究原理 异步编程之Promise(3):拓展进阶 异步编程之Generator(1)--领略魅 ...

  5. JS 异步系列 —— Promise 札记

    Promise 研究 Promise 的动机大体有以下几点: 对其 api 的不熟悉以及对实现机制的好奇; 很多库(比如 fetch)是基于 Promise 封装的,那么要了解这些库的前置条件得先熟悉 ...

  6. node.js异步编程解决方案之Promise用法

    node.js异步编程解决方案之Promise var dbBase = require('../db/db_base'); var school_info_db = require('../db/s ...

  7. 一个例子读懂 JS 异步编程: Callback / Promise / Generator / Async

    JS异步编程实践理解 回顾JS异步编程方法的发展,主要有以下几种方式: Callback Promise Generator Async 需求 显示购物车商品列表的页面,用户可以勾选想要删除商品(单选 ...

  8. generator和promise配合解决js异步地狱问题

    为何要使用generator函数和promise? js的异步地狱一直是困扰前端程序员的一个头疼的问题 比如说我要获取还有列表,一般来说会使用ajax来获取 $.ajax(...等等,function ...

  9. js 深入原理讲解系列-Promise

    js 深入原理讲解系列-Promise 能看懂这一题你就掌握了 js Promise 的核心原理 不要专业的术语,说人话,讲明白! Q: 输出下面 console.log 的正确的顺序? const ...

随机推荐

  1. error 'there is already an open datareader associated with this command which must be closed first'

    This can be easily solved by allowing MARS in your connection string. Add MultipleActiveResultSets=t ...

  2. Redis查询&JDBC查询&Hibernate查询方式的效率比较...

    比较三种查询方式查询效率对比...我是用的JavaWeb的方式通过通过JSP页面查询的填写查询的参数...给予反馈.... 整个demo的下载地址:http://files.cnblogs.com/f ...

  3. 【树】Flatten Binary Tree to Linked List(先序遍历)

    题目: Given a binary tree, flatten it to a linked list in-place. For example,Given 1 / \ 2 5 / \ \ 3 4 ...

  4. 《Mysql技术内幕,Innodb存储引擎》——文件、表

    文件 日志 错误日志 对Mysql启动.运行和关闭过程进行记录,通过SHOW VARIABLES LIKE 'log_error'查看日志文件位置. 慢查询日志 Mysql启动时设置一个阈值,运行时间 ...

  5. 原生JavaScript 导出excel表格(兼容ie和其他主流浏览器)

    因同事的需求是想前端导出excel表格,网上找了一些demo,自己修改了一下,可能以后会用到,记录下来吧,兼容ie和一些主流浏览器,ie可能会报错,原因参考 这里,edge 浏览器还没有办法导出,正在 ...

  6. 常用算法2 - 广度优先搜索 & 深度优先搜索 (python实现)

    1. 图 定义:图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合. 简单点的说:图由节点和边组成.一 ...

  7. Extjs报错处理

    错误信息: IE:SCRIPT1009: 缺少 '}' FF: SyntaxError: identifier starts immediately after numeric literal ... ...

  8. JavaScript部分兼容性函数

    1.getElementsByClassName() function getElementsByClassName(node,classname){ if(node.getElementsByCla ...

  9. MVC初级教程(二)

    演示产品源码下载地址:http://www.jinhusns.com/Products/Download 

  10. [日常] 搭建golang开发环境

    下载目录:https://studygolang.com/dl32位选 go1.10.linux-386.tar.gz64位选 go1.10.linux-amd64.tar.gz uname -a查看 ...