JS异步发展之Promise

105 阅读1分钟

异步的发展历程:

callback->promise(ES6)->async/await(ES7)

为什么使用异步?

同步性能低,而且会阻塞主线程,所以用异步。

异步的缺点有哪些?

    1. 异步方法如果出错了,try/catch不能捕获其中的错误。
    1. 异步方法获取的结果,不能通过return直接返回。
    1. 回调函数多次嵌套的写法不优雅,不易捕获异常,调试困难(即所谓的回调地狱)。

传统的callback方式存在如下问题:

  • 问题1:两个异步请求 第二个请求依赖于第一个请求的返回结果(多层嵌套).
  • 问题2: 两个异步请求 同时拿到两个异步请求的结果 [result1,result2]. (问题2的解决方案:after,发布订阅模式)

ES6中的Promise可以轻松解决传统callback中的上述两个问题。

//1) 读取两个文件,第一个文件里内容是第二个文件的路径,要求输出第二个文件的内容。
let fs = require('fs');
function read(path, encoding) {
  return new Promise((resolve, reject) => {
    fs.readFile(path, encoding, function (err, data) {
      if (err) return reject(err);
      resolve(data);
    });
  })
} 
read('./1.txt', 'utf8').then(data => {
  return read(data, 'utf8');//执行结果传递给下一次then
},err=>{  
  console.log(err);
}).then(data => {
  return [data];
}).catch(err=>{
  console.log(err);
});

成功的回调 or 失败的回调执行后可以返回一个promise, 会将这个promise的执行结果传递给下一次then.

// 2) Promise.all()可以解决多个异步请求问题
// 等待两个promise都执行完成后
// all方法会返回一个新的promise
// 如果有一个失败就失败了
Promise.all([read('1.txt', 'utf8'), read('2.txt', 'utf8')]).then(data=>{
  console.log(data);
},err=>{
  console.log(err);
});

创建一个一出生就成功或者失败的promise:

Promise.resolve('123').then(data=>{
  console.log(data);
})
Promise.reject('123').then(null,err=>console.log(err))