一文看懂JS异步编程(Promise)

前言

JS中异步编程主要分为四种,其中回调和生成器不是这篇文章的重点,本文主要集中在Promise和async, await上面。

Promise

首先我们看Promise的几个特点:

  1. 回调函数延迟绑定即then方法,它可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个参数可选,一般使用catch触发,无论那种方式都是把回调函数延迟执行。
  2. 返回值穿透。
readFilePromise('1.json').then(data => {
    return readFilePromise('2.json');
}).then(data => {
    return readFilePromise('3.json');
}).then(data => {
    return readFilePromise('4.json');
});

可以看到then方法返回的Promise可以在后面继续使用。

  1. 错误冒泡,整个thenable链式调用发生的每一处错误都可以由最后一个catch捕获。

then方法

then毫无疑问是这些方法种最重要的,我学习链式调用时下面代码解答了我很多疑惑。

注意then接收两个参数,都是函数,第二个可选。

同时函数返回的可以是一个值也可以是一个Promise,如果是前者,他会调用一个Promise包裹传递给后面使用;如果是后者同样也会调用给后面使用。

var p = new Promise(function(resolve, reject){
  resolve(1);
});
p.then(function(value){               //第一个then
  console.log(value);
  return value*2;
}).then(function(value){              //第二个then
  console.log(value);
}).then(function(value){              //第三个then
  console.log(value);
  return Promise.resolve('resolve'); 
}).then(function(value){              //第四个then
  console.log(value);
  return Promise.reject('reject');
}).then(function(value){              //第五个then
  console.log('resolve: '+ value);
}, function(err){
  console.log('reject: ' + err);
})

接着来看一段执行顺序的判断:

var p1 = new Promise( function(resolve,reject){
  console.log('start1')
  resolve( 1 );	  
});

p1.then(
  function(value){
    console.log('p1 then value: ' + value);
  }
).then(
  function(value){
    console.log('p1 then then value: '+value);
  }
);

var p2 = new Promise(function(resolve,reject){
  resolve( 2 );	
});

p2.then(
  function(value){
    console.log('p2 then value: ' + value);
  }
).then(
  function(value){
    console.log('p2 then then value: ' + value);
  }
).then(
  function(value){
    console.log('p2 then then then value: ' + value);
  }
);
console.log('start2')

最后的执行结果为:

VM382:2 start1
VM382:33 start2
VM382:8 p1 then value: 1
VM382:22 p2 then value: 2
VM382:12 p1 then then value: undefined
VM382:26 p2 then then value: undefined
VM382:30 p2 then then then value: undefined

resolve和reject

关于resolve,它可以接受普通值,也可以接收一个Promise

const p1 = new Promise(function (resolve, reject) {
  setTimeout(() => reject(new Error('fail')), 3000)
})

const p2 = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(p1), 1000)
})

p2
  .then(result => console.log(result))
  .catch(error => console.log(error))

如这一段程序,3000ms之前p1的状态是pendding,由于这是p2中resolve依赖p1的状态,所以p2的状态我们可以忽略了。

这时p2走then方法,result即为一个Promise,状态pendding。

3000ms后走catch,这是因为p1状态改变,而p2直接转发了p1的reject。

all和race

一个是都完成才算成功,一个是谁跑得快谁成功。

当然关于all和race还有一些细节,如传的是值而不是promise的话会先进行Promise处理;error若在Promise中声明,是不会走all的catch方法的等等。

发布了371 篇原创文章 · 获赞 391 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_43870742/article/details/104048151