所谓 Promise,就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。
Promise的出现主要是解决回调地狱的问题,比如你需要结果需要请求很多个接口,这些接口的参数需要另外那个的接口返回的数据作为依赖,这样就需要我们一层嵌套一层,但是有了Promise 我们就无需嵌套
Promise.resolve()//表示成功Promise.reject()//表示失败Promise.prototype.then()//成功时要干嘛Promise.prototype.catch()//失败时要干嘛Promise.all() // 所有的完成Promise.all([p1,p2,p3])
var p = new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('get', 'url');
xhr.send(); xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
resolve(xhr.responseText); }
setInterval(function() {
reject(new Error('连接超时')); }, 2000) } });
p.then(function(data) { console.log(data) }).catch(function(err) { if (err) throw err; }).finally(function() { console.log('asdf') })
let p1 = new Promise((resolve, reject) => { resolve('成功了') })
let p2 = new Promise((resolve, reject) => { resolve('success') })
let p3 = Promse.reject('失败')
Promise.all([p1, p2]).then((result) => { console.log(result) //['成功了', 'success'] })
.catch((error) => { console.log(error) }) Promise.all([p1,p3,p2])
.then((result) => { //全部成功了才执行 console.log(result) })
.catch((error) => { //有一个失败了就是失败 console.log(error) })
let p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('success') },1000) })
let p2 = new Promise((resolve, reject) => { setTimeout(() => { reject('failed') }, 500) }) Promise.race([p1, p2]).then((result) => { console.log(result) }).catch((error) => { console.log(error) // 打开的是 'failed' })
接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术。在异步编程中,还有一种常用的解决方案,它就是Generator生成器函数。顾名思义,它是一个生成器,它也是一个状态机,内部拥有值及相关的状态,生成器返回一个迭代器Iterator对象,我们可以通过这个迭代器,手动地遍历相关的值、状态,保证正确的执行顺序
es6 提供的 generator函数
Generator的声明方式类似一般的函数声明,只是多了个 * 号,并且一般可以在函数内看到yield关键字
function* showWords() {
yield 'one'; //yield关键字后面跟的是任务
yield 'two';
return 'three'; //return表示之后的yield语句将不再执行
}
var show = showWords();
show.next() // {done: false, value: "one"}
show.next() // {done: false, value: "two"}
show.next() // {done: true, value: "three"}
show.next() // {done: true, value: undefined}
yield后面接的是任务,如果任务只是个简单的数据,就可以直接输出,若是yield后面的任务是一个对象或者函数的话yield关键字就不好用了,函数体会停留在这里,这时候就要在yield后面加个 * 号,yield*表示自动遍历对象
async await函数语法与generator函数相似,只要把 * 号换成async,然后把yield换成await就可以
Generator 函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。
async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。
co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。
async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。进一步说,async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。
nodejs中是事件驱动的,有一个循环线程一直从事件队列中取任务执行或者I/O的操作转给后台线程池来操作,把这个循环线程的每次执行的过程算是一次轮询.
即时计时器立即执行工作,它是在事件轮询之后执行,为了防止轮询阻塞,每次只会调用一个。
它和setImmediate()执行的顺序不一样,它是在事件轮询之前执行,为了防止I/O饥饿,所以有一个默认process.maxTickDepth=1000来限制事件队列的每次循环可执行的nextTick()事件的数目。
process.nextTick()属于idle观察者,setImmediate()属于check观察者.在每一轮循环检查中,idle观察者先于I/O观察者,I/O观察者先于check观察者.在具体实现上,process.nextTick()的回调函数保存在一个数组中,
setImmediate()的结果则是保存在链表中.
在行为上,process.nextTick()在每轮循环中会将数组中的回调函数全部执行完.
而setImmediate()在每轮循环中执行链表中的一个回调函数.
//加入2个nextTick()的回调函数
process.nextTick(function(){
console.log("nextTick延迟执行A");
});
process.nextTick(function(){
console.log("nextTick延迟执行B");
setImmediate(function(){
console.log("setImmediate延迟执行C");
});
process.nextTick(function(){
console.log("nextTick延迟执行D");
});
});
//加入两个setImmediate()回调函数
setImmediate(function(){
console.log("setImmediate延迟执行E");
process.nextTick(function(){
console.log("强势插入F");
});
setImmediate(function(){
console.log("setImmediate延迟执行G");
});
});
setImmediate(function(){
console.log("setImmediate延迟执行H");
process.nextTick(function(){
console.log("强势插入I");
});
process.nextTick(function(){
console.log("强势插入J");
});
setImmediate(function(){
console.log("setImmediate延迟执行K");
});
});
console.log("正常执行L");
正常执行L
nextTick延迟执行A
nextTick延迟执行B
nextTick延迟执行D
setImmediate延迟执行E
setImmediate延迟执行H
setImmediate延迟执行C
强势插入F
强势插入I
强势插入J
setImmediate延迟执行G
setImmediate延迟执行K
Process finished with exit code 0