Promise相关

https://segmentfault.com/a/1190000039275224
默认返回一个new Promise,其他的,在这个返回里面去做

  • Promise.all:如果都成功则返回成功数据(resolve),如果有一个失败了,则立即reject返回,即有失败的下面就不走了
  • Promise.allSettled:会返回所有数据,成功的返回状态和值,不成功的返回状态和原因,即便中间不成功也不会打断执行,会将所有接口运行完才做数据返回
  • Promise.any:任意一个promise成功就返回这个值
  • Promise.race:任意一个promise成功或者失败后,返回这个值,成功就返回成功值,失败返回失败值
  • Promise.resolve(value):返回一个状态由给定 value 决定的 Promise 对象
  • Promise.reject(reason):返回一个状态为已拒绝的 Promise 对象,并将给定的失败信息传递给对应的处理函数

有两种方式能拿到错误值,一种是.catch;另一个是在then的第二个参数里能直接拿到reject的原因,并且如果我在.then里拿到了错误原因,那.catch就拿不到错误原因了,走不到这步了

const pr = new Promise((resolve, reject) => {
    reject(111)
})
// 在.then里处理的reject的原因了,所以不会走到.catch的方法里
// 所以结果为:then 111
pr.then((value) => {}, (reason) => {console.log('then', reason)}).catch(error => console.log('catch', error))     

// 这里没有在.then里去做reject的处理,所以可以走到.catch中间
// catch 111
pr.then((value) => {}).catch(error => console.log('catch', error))

// 后续的then不会随着前面的catch有变化,会一直继续向下做请求,展示then的值
// then 111, 0000
pr.then((value) => {}, (reason) => {console.log('then', reason)})
.catch(error => console.log('catch', error))
.then(() => console.log('0000'))

// 即使使用了finally也会继续走到后面的then里,只要后面有
// 结果:22、 222222、2345
pr.then((value) => {})
    .catch((ee) => console.log('22'))
    .finally(() => console.log('222222'))
    .catch(ee => console.log(ee))
    .then(value => console.log(2345)) 

// finally如果抛出去一个error,那么后续也会被catch接住
// 22、Error: 123,2345
pr.then((value) => {})
    .catch((ee) => console.log('22'))
    .finally(() => {throw Error('123')})
    .catch(ee => console.log(ee))
    .then(value => console.log(2345))

Promise.all

// arr 传过来的接口请求
const Promise_all = (arr) => {
  if (!Array.isArray(arr)) {
    throw new Error('参数错误')
  }
  // 重点需要返回一个promise
  return new Promise((resolve, reject) => {
    // 一共完成了多少个
    let num = 0;
    // 返回的结果数组
    const result = [];
    for(let i = 0; i < arr.length; i++) {
      // 单条去调用promise,成功后的结果回显到result数组
      // then有两个函数参数,一个是成功,一个是失败
      Promise.resolve(arr[i]).then(res => {
        num++;
        result[i] = res;
        // 如果result数组的长度与arr相同了,则说明处理完了
        if (num === arr.length) {
          return resolve(result);
        }
      }, reason => {
        // 失败了直接终止
        return reject(reason);
      })
    }
  })
}

Promise.race

// promise_race
const promise_race = (arr) => {
  if (!Array.isArray(arr)) {
    throw new Error('失败参数')
  }
  return new Promise((resolve, reject) => {
    for(let i = 0; i < arr.length; i++) {
      Promise.resolve(arr[i]).then(res => {
        resolve(res)
      }, reason => {
        reject(reason)
      })
    }
  })
}

Promise

class MyPromise {

    // 构造函数
    constructor(executor) {
      this.state = "pending";
      this.value = undefined;
      this.reason = undefined;
      this.onResolvedCallbacks = [];
      this.onRejectedCallbacks = [];
  
      // promise内置resolve
      const resolve = (value) => {
        if (this.state === "pending") {
          this.state = "fulfilled";
          this.value = value;
          this.onResolvedCallbacks.forEach((callback) => callback(value));
        }
      };
  
      // promise内置reject
      const reject = (reason) => {
        if (this.state === "pending") {
          this.state = "rejected";
          this.reason = reason;
          this.onRejectedCallbacks.forEach((callback) => callback(reason));
        }
      };
  
      try {
        executor(resolve, reject);
      } catch (error) {
        reject(error);
      }
    }
  
    // then方法
    then(onFulfilled, onRejected) {
      onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (value) => value;
      onRejected = typeof onRejected === "function" ? onRejected : (reason) => { throw reason };
  
      const promise2 = new MyPromise((resolve, reject) => {
        if (this.state === "fulfilled") {
          setTimeout(() => {
            try {
              const x = onFulfilled(this.value);
              this.resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          }, 0);
        } else if (this.state === "rejected") {
          setTimeout(() => {
            try {
              const x = onRejected(this.reason);
              this.resolvePromise(promise2, x, resolve, reject);
            } catch (error) {
              reject(error);
            }
          }, 0);
        } else {
          this.onResolvedCallbacks.push(() => {
            setTimeout(() => {
              try {
                const x = onFulfilled(this.value);
                this.resolvePromise(promise2, x, resolve, reject);
              } catch (error) {
                reject(error);
              }
            }, 0);
          });
  
          this.onRejectedCallbacks.push(() => {
            setTimeout(() => {
              try {
                const x = onRejected(this.reason);
                this.resolvePromise(promise2, x, resolve, reject);
              } catch (error) {
                reject(error);
              }
            }, 0);
          });
        }
      });
  
      return promise2;
    }
    // catch方法
    catch(onRejected) {
      return this.then(null, onRejected);
    }
  
    // finally方法
    finally(onFinally) {
      return this.then(
        (value) => MyPromise.resolve(onFinally()).then(() => value),
        (reason) =>
          MyPromise.resolve(onFinally()).then(() => {
            throw reason;
          })
      );
    }

    // Promise.resolve方法
    resolvePromise(promise2, x, resolve, reject) {
      if (promise2 === x) {
        // 链循环了
        reject(new TypeError("Chaining cycle detected for promise"));
      }
  
      let called = false;
  
      if (x instanceof MyPromise) {
        x.then((value) => {
            // resolve方法
            this.resolvePromise(promise2, value, resolve, reject);
          },
            // reject方法
          (reason) => {
            if (!called) {
              called = true;
              reject(reason);
            }
          });
      } 
      else if (x !== null && (typeof x === "object" || typeof x === "function")) {
        try{
            const then = x.then;
            if (typeof then === "function") {
                then.call(x, 
                    (y) => {
                        // resolve
                        if (!called) {
                            called = true;
                            this.resolvePromise(promise2, y, resolve, reject);
                        }
                    },
                    // reject
                    (reason) => {
                        if (!called) {
                            called = true;
                            reject(reason);
                        }
                    }
                );
            } else {
                resolve(x);
            }
        } catch {
            resolve(x);
        }
      } 
      else {
        resolve(x);
      }
    }
  
    static resolve(value) {
        if (value instanceof MyPromise) {
        return value;
        }
        return new MyPromise((resolve) => resolve(value));
    }
    
    static reject(reason) {
        return new MyPromise((_, reject) => reject(reason));
    }
}
限制最大请求数,最快请求完毕

假如等待请求接口1000个,限制每次只能发出100个。即同一时刻最多有100个正在发送的请求。每当100个之中有一个请求完成时,则从待请求的接口(即剩余的900个待请求接口)中再取出一个发出。保证当前并发度仍旧为100。直至全部接口请求完成。

  let count = 0;  // 当前正在运行的接口数量
  const res = []  // 最后的结果
  // 判断是否调度函数
  const panDuan = (urls, max) => {
    if (urls.length > 0 && count < max) {
      resFn(urls, max)
    }
  }

  // 做接口数据请求
  const resFn = async (urls, max) => {
    count++;
    const prom = await new Promise((resolve, reject) => {
      Promise.resolve(urls.shift()).then(value => {
        res.push(value);
        resolve(value)
      }, reason => {
        res.push(reason);
        reject(reason)
      })
    }) 
    prom.then(() => {
      count--;
      panDuan(urls, max)
    })
  }

  // 循环处理
  const fn1 = (urls, max) => {
    for(let i = 0; i < max; i++) {
      resFn(urls)
    }
    return res
  }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,376评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,126评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,966评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,432评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,519评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,792评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,933评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,701评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,143评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,488评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,626评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,292评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,896评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,324评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,494评论 2 348

推荐阅读更多精彩内容

  • 在 javascript 中, 所有代码都是单线程执行的。 由于这个缺陷,导致 javascript 的所有网络操...
    Robot_Lee阅读 597评论 0 0
  • 可供参考资料 1、了解 Promise 吗? 了解Promise,Promise是一种异步编程的解决方案,有三种状...
    coderfl阅读 252评论 0 0
  • 异步编程 *fs文件操作*数据库操作*ajax*定时器在promise之前的解决方式: 旧的解决方法:必须在启动异...
    Spinach阅读 435评论 0 2
  • Promise 检测图片 检测图片是否加载成功,成功就正常显示,失败就展示默认图片 休眠的实现方法 基本用法 有一...
    池鱼_故渊阅读 246评论 0 1
  • 0、底层 Event Loop事件循环:就是一个执行消息队列的机制 宏任务 微任务为了解决这种情况,将任务分为了同...
    月光一族阅读 2,888评论 7 42