Promise的基本使用

126 阅读4分钟

前言

Promise对于前端来说一点都不陌生,主要是用来异步操作。一句话很经典---支持链式调用,解决回调地狱问题。

基本使用

重要的概念

Promise 对象代表一个异步操作,有三种状态,pending进行中,fulfilled(resolved)已成功,rejected 已失败,只有异步操作的结果,才可以决定当前是哪一种状态。

一旦状态改变,就不会再变,Pomise 对象状态改变只有两种可能,从 pending 改到fulfilled 或者从 pending 改到 rejected。

promise方法接受两个参数,第一个是参数是resolve,作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;第二个参数是reject,作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

Promise对象身上有 .then()方法,第一个参数为成功时的回调,第二个方法为失败时的回调。Promise的构造函数是同步执行的。

const promise = new Promise((res, rej) => {
  //包裹一个异步的操作(计时器、请求、数据库、读取文件),成功resolve(),失败reject()
  setTimeout(() => {
    rej("错误")
  }, 1000)
})
//.then()方法可以执行成功和失败的回调
promise.then((val) => {
  console.log(val);
}, (err) => {
  console.log(err);   //错误
})

当然也可以直接执行失败的回调

const promise = new Promise((res, rej) => {
  //包裹一个异步的操作(计时器、请求、数据库、读取文件),成功resolve(),失败reject()
  setTimeout(() => {
    rej("错误")
  }, 1000)
})
// .catch()方法只能执行失败的回调
promise.catch((err) => {
  console.log(err);    //错误
})

Promise.resolve()

  • 如果传入参数为非Promise类型的对象,则返回的结果为成功promise对象,成功的参数就是传入的参数
let promise = Promise.resolve(1);
promise.then((val) => {
  console.log(val);  // 1
})
  • 如果传入参数为Promise类型的对象,则参数为传入Promise对象成功或失败的结果
let promise = Promise.resolve(new Promise((res, rej) => {
  setTimeout(() => {
    res('成功')
  }, 2000)

}))

promise.then((val) => {
  console.log(val);  //成功
}).catch((err) => {
  console.log(err);
})

Promise.reject()

  • 不管传入的是什么,都是执行失败的回调,传入的是什么,失败返回的参数就是什么
let promise = Promise.reject(1);
promise.catch((val) => {
  console.log(val);   //1
})

let promise1 = Promise.reject(new Promise((res, rej) => {
  res(312)
}))

promise1.catch((val) => {
  console.log(val);  //Promise { 312 }
})

Promise.all()

常用的地方是可以用来并发请求

  • 参数为Promise对象数组
  • 当传入参数的Promise全都成功,返回结果为成功的Promise对象数组,有一个或多个失败,返回结果为第一个失败的Promise传出的参数
let promise = new Promise((res, rej) => {
  setTimeout(() => {
    res(1)
  },1000)
})
let promise1 = new Promise((res, rej) => {
  setTimeout(() => {
    res(2)
  },1000)
})

let all = Promise.all([promise, promise1])
all.then((val) => {
  console.log(val);  //[1,2]
})
let promise = new Promise((res, rej) => {
  setTimeout(() => {
    rej(1)
  },1000)
})
let promise1 = new Promise((res, rej) => {
  setTimeout(() => {
    rej(2)
  },1000)
})

let all = Promise.all([promise, promise1])
all.then((val) => {
  console.log(val);
}).catch((err) => {
  console.log(err);  // 1
})

Promise.race()

  • 参数Promise对象数组
  • 返回一个新的Promise对象,为第一个完成Promise状态,不管失败还是成功。
let promise = new Promise((res, rej) => {
  setTimeout(() => {
    res(1)
  }, 100)

})
let promise1 = new Promise((res, rej) => {
  setTimeout(() => {
    rej(2)
  }, 1000)
})


let race = Promise.race([promise, promise1])
race.then((val) => {
  console.log(val);  //1
}).catch((err) => {
  console.log(err);
})

Promise的链式调用

这就要说一下then()方法的返回结果是什么

  • 如果then()方法返回的结果是非Pomise对象,那么执行的是成功的回调,参数为then()方法返回的结果
  • 如果then()方法返回是结果是Pomise对象,那么返回的Pomise对象状态决定了then()方法的状态,返回的Pomise的结果就是then()方法的结果
function promise() {
  return new Promise((resolve, reject) => {
    resolve("A");
  })
}
promise().then(
  data => {
    console.log(data);  //A
    var B = new Promise((resolve, reject) => {
      resolve("B");
    })
    return B;
  }
).then((data) => {
  console.log(data);  //B
}
).then((data) => {
  console.log(data);   //undefined
})

当链中有执行失败的结构,抛出了一个错误的异常;所以不会走then;而是直接走catch;,也可以叫异常穿透

function promise() {
  return new Promise((resolve, reject) => {
    resolve("A");
  })
}
promise().then(
  data => {
    console.log(data);  //A
    var B = new Promise((resolve, reject) => {
      reject("B");
    })
    return B;
  }
).then((data) => {
  console.log(data);
}).then((data) => {
  console.log(data);
}).catch((err) => {
  console.log(err); //B
})

中断Promise链

  • 有且只有一种方式去中断Promise;让Promise的状态是padding
let promise = new Promise((res, rej) => {
  setTimeout(() => {
    res(1)
  }, 1000)
})

promise.then((val) => {
  console.log(val);  //1
  //中断
  return new Promise(() => { })
}).then((val1) => {
  console.log(val1)
}).catch((err) => {
  console.log(err);
})