我的Promise秘密初探之小试牛刀

426 阅读4分钟

一、前言概述

在前端开发中,相信很多读者都使用过AJAX,这种比较🐂 逼的异步处理方式,确实在一定程度上方便和简化了我们的某些需求,但有时候也会遇到在一个操作中,会需要多个异步请求的情况,在以往的处理中,比如笔者就曾做过2个及多个AJAX层层嵌套着处理的方式,这种方式,在当时看上去也可以满足一般的需求,但看着别扭,总觉得哪里不爽;

$.ajax({
    cache: false,
    type: 'POST',
    url: url1,
    dataType: 'json', 
    success: function (data) {
        $.ajax({
            cache: false,
            type: 'POST',
            url:url2,
            data: { para: list},
            dataType: 'json',
            success: function(result) {
                ......
            }
        })
    }
})

如上,魔鬼嵌套;

很快,随着ES6的发布,Promise横空出世,之前多个AJAX多层嵌套的处理方式,看上去显得那么的low,如此的恶劣不堪,反观Promise,高端大气上档次-------哈哈,是不是有点喜新厌旧的嫌疑啊------瞬间,让我喜欢上了,有点一见钟情的赶脚😆

整个就是一大方优雅的典范啊:

readFile(filename).then(function (data) {
    return data;
}).then(function (data) {
    return readFile(data);
}).then(function (data) {
    console.log(data);
}).catch(function(err){
    ......
});

二、原理浅析

  1. Promise 名如其实,Promise本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果。 什么时候会用到过一段时间?答案是异步操作,异步是指可能比较长时间才有结果的才做,例如网络请求、读取本地文件等;

    在这个过程中,Promise会经历三个状态:

  • Pending Promise对象实例创建时候的初始状态
  • Fulfilled 可以理解为成功的状态
  • Rejected 可以理解为失败的状态

then 方法就是用来指定Promise 对象的状态改变时确定执行的操作,resolve 时执行第一个函数(onFulfilled),reject 时执行第二个函数(onRejected)

  1. 示例分析:
let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        if(Math.random()>0.5)
            resolve('This is resolve!');
        else
            reject('This is reject!');
    }, 1000);
});
promise.then(Fulfilled,Rejected)
  • 构造一个Promise实例需要给Promise构造函数传入一个函数。
  • 传入的函数需要有两个形参,两个形参都是function类型的参数。
    • 第一个形参运行后会让Promise实例处于resolve状态,所以我们一般给第一个形参命名为resolve,使 Promise 对象的状态改变成成功,同时传递一个参数用于后续成功后的操作
    • 第一个形参运行后会让Promise实例处于reject状态,所以我们一般给第一个形参命名为reject,将 Promise 对象的状态改变为失败,同时将错误的信息传递到后续错误处理的操作

三、小试牛刀

经过一些时间的学习和摸索,笔者在ES6自带的Promise的基础上,实现了对其all、race、resolve、reject的功能模拟;

  1. Promise.all
  • 参数:接受一个数组,数组内都是Promise实例。
  • 返回值:返回一个Promise实例,这个Promise实例的状态转移取决于参数的Promise实例的状态变化。当参数中所有的实例都处于resolve状态时,返回的Promise实例会变为resolve状态。如果参数中任意一个实例处于reject状态,返回的Promise实例变为reject状态。
  • 代码如下
Promise.all = function(promises){
 return new Promise(function(resolve,reject){
   let done = gen(promises.length,resolve);
   for(let i=0;i<promises.length;i++){
     promises[i].then(function(data){
       done(i,data);
     },reject);
   }
 });
}
  1. Promise.race
  • 参数:接受一个数组,数组内都是Promise实例
  • 返回值:返回一个Promise实例,这个Promise实例的状态转移取决于参数的Promise实例的状态变化。当参数中任何一个实例处于resolve状态时,返回的Promise实例会变为resolve状态。如果参数中任意一个实例处于reject状态,返回的Promise实例变为reject状态。
  • 代码如下:
Promise.race = function(promises){
  return new Promise(function(resolve,reject){
    for(let i=0;i<promises.length;i++){
      promises[i].then(resolve,reject);
    }
  });
}
  1. Promise.resolve
  • 该方法返回一个Promise实例,这个实例处于resolve状态。 会根据传递的参数不同而有不同的功能:
  • 当参数是值(对象、数组、字符串等)类型的:作为resolve传递出去的值;
  • 当参数是Promise实例:则原封不动返回;
  • 代码如下:
//返回一个立刻成功的promise
//但该方法,需要传入一个promise,但你只有一个普通的值,你就可以通过这个方法
//把这个普通的值(string number object)转成一个promise对象
Promise.resolve = function(value){
  return new Promise(function(resolve){
    resolve(value);
  });
}
  1. Promise.reject
  • 该方法返回一个Promise实例,这个实例处于reject状态。
  • 参数一般就是抛出的错误信息。
  • 代码如下:
//返回一个立刻失败的promise
Promise.reject = function(reason){
  return new Promise(function(resolve,reject){
    reject(reason);
  });
}

四、小结

以上就是在下对前端经常遇到的异步处理方式的前认与后知;本人自知才疏学浅,如果有一些理解的有失偏颇之处,欢迎各位随时拍砖与指正~!

当然,如果对您还有点作用的话,还望您评论鼓励,以资我继续前行,小可不胜感激~!