从入门到放弃之promise用法(上)

885 阅读4分钟

参考文献

一、promise的简述

含义

  • Promise是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了Promise对象。
  • 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

简单说promise就是一个承诺,未来才会实现。比如媳妇等我有钱了给你买包, 先等着,给你个承诺,等有钱了再买。承诺就是一个等待态,你可以设置成功或者失败,即买包和不买包,这就是下面所说的三个状态了。

特点

  • 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、resolves(已成功)和rejected(已失败)。
  • 一旦状态改变,就不会再变。只有两种可能:从pending变为fulfilled和从pending变为rejected。

简单说就是Promise对象有三种状态,一旦成功就不能失败,一旦失败就不能成功

主要解决回调地狱,函数嵌套的问题

  • 比如看我们下面的代码
let fs = require("fs");
fs.readFile("a.txt",'utf8',function(data1){ 
    fs.readFile("b.txt",'utf8',function(data2){ 
        console.log(data1,data2);
    })
})

data2数据需要依赖上一次的返回结果data1时,就会造成嵌套问题,当无限嵌套下去,就会形成回调地狱问题, 下面我们来看promise基础用法,怎么解决这类问题

二、promise的基础用法

创建一个promise实例

  • Promise本身是一个构造函数,需要我们new 一个实例,传递一个函数作为参数(我们称之为执行器函数 executor),函数接收两个参数 resolve(成功函数) 、reject(失败函数)
let p =new Promise((resolve,reject)=>{
    //执行器默认在new时就会被调用,立即执行 
    console.log("1")
    resolve("123") //成功函数resolve,传递了123
});

这有什么用呢,我们来看p的then方法怎么得到123

then链式写法

  • then中传递两个函数,第一个函数对应成功时候回调(即resolve('123')),第一个函数对应失败时候回调(即reject('123'))
  • 这样的话就把resolve('123')中的123,被then中成功回调所捕获 data就是123啦,如果传递reject('123')就会被失败回调捕获
p.then(value=>{ 
    //value指的上面resolve传递的参数,成功的原因
    console.log(value) 
},err=>{
    //失败的原因, reject传递的参数
     console.log(err)
})
.then(value=>{
    console.log(value)
},err=>{
     console.log(err)
})
  • 回想下我们如何用promise解决上述嵌套问题
let fs = require('fs');
function read(file){
    return new Promise(function(resolve,reject){
        fs.readFile(file,'utf8',function(err,data){
            if (err) {
                return reject(err);
            }
            resolve(data);
        })
    })
}
read('./a.txt').then(function(data){
    return read('./b.txt');
}).then(function(data){
    console.log(data);
})
  • 上述的写法是不是更具有流程感
  • then还可以穿透,什么意思呢,直接上代码
let Promise = require('./Promise');
let promise = new Promise((resolve,reject)=>{
  resolve('hello');
});
promise.then().then().then(data=>{ //可以无限的then,但结果仍会拿到
  console.log(data); //'hello'
},err=>{
  console.log('err',err);
})

错误处理catch

  • catch捕获错误,与try/catch语句有类似的功能,可以把then第二个参数省去,在最后面写上.catch
p.then().then().catch(err=>{
    console.log(err)
})

Promise.all()

  • Proise.all()在所有的异步操作执行完后才执行的回调,接受一个数组,数组中每项都应是一个promise实例,Promise.all()返回的结果也是一个promise,因此也可以.then下去,上一段代码吧
let fs = require("fs");
function read(path) {
  return new Promise((resolve, reject) => {
    fs.readFile(path, 'utf8', function(err, data) {
      if (err) return reject(err);
      resolve(data);
    });
  });
}
Promise.all([read("1.txt"), read("2.txt")]).then( //可以then说明Promise.all()返回结果也是promise
  data => {
    console.log(data);// [1.txt内容,2.txt内容]
  },
  err => {
    console.log(err);
  }
);

Promise.race()

  • 用法跟Promise.all()很像,指的是谁跑得快,执行谁的回调。
let fs = require("fs");
function read(path) {
  return new Promise((resolve, reject) => {
    fs.readFile(path, 'utf8', function(err, data) {
      if (err) return reject(err);
      resolve(data);
    });
  });
}
Promise.all([read("1.txt"), read("2.txt")]).then( //可以then说明Promise.all()返回结果也是promise
  data => {
    console.log(data);// [1.txt或者2.txt内容] 
  },
  err => {
    console.log(err);
  }
);

读到这里,相信大家看到这里都应该大概对promise有一定的了解,下一章带领大家手写一套符合promise A+规范的代码。