• 关于 【顺序执行Promise】 的一些理解


    前言

      近日工作上有一个需求,页面上有一个历史记录的东西,存储了最近使用的10张图片(大概知道下背景就好,不用深究)每一次页面刷新,ready后,要去服务器拉取那几张图片的URL,以便在页面上展示,因为产品要求历史记录的图片要按使用的时间顺序排列展示,我想了一下,决定按顺序发起【拉取图片URL】的请求(不要问我为什么)。在使用过程中碰到了问题,网友的答案我不大满意,所以特此总结一下。

    套路

      处理这类问题的方法有以下两种:

    • Promise链式执行
    • 利用async/await

      我姑且认为大家的Promise是这么发出去的:

     1 /**
     2  * 不带参数
     3  */
     4 function p1() {
     5     // ... 前置处理
     6     return new Promise((resolve, reject) => {
     7         // ... 业务代码
     8 
     9     })
    10 }
    11 
    12 p1().then(res => {
    13     // 后续处理
    14 }, err => {
    15     // 后续处理
    16 })
     1 /**
     2  * 带参数
     3  */
     4 function p1(param) {
     5     // ... 前置处理
     6     return new Promise((resolve, reject) => {
     7         // 业务代码
     8 
     9     })
    10 }
    11 
    12 p1(param).then(res => {
    13     // 后续处理
    14 }, err => {
    15     // 后续处理
    16 })

      接下来我将分【带参数】和 【不带参数】两种情况,分别说明。

    代码

    不带参数

    链式执行法

     1 function p1() {
     2     return new Promise((resolve, reject) => {
     3         resolve(1);
     4     })
     5 }
     6 
     7 function p2() {
     8     return new Promise((resolve, reject) => {
     9         resolve(2);
    10     })
    11 }
    12 
    13 function queue(...t) {
    14     // 返回一个resolve状态的Promise对象,方便第一次在then中调用异步任务
    15     let _queue = Promise.resolve();
    16     let result = [];
    17     t.forEach(p => {
    18         _queue = _queue.then(p).then(res => {
    19             result.push(res);
    20             // 为了在最后一个then中获取到结果,因为then返回的是一个新的Promise实例
    21             // 如果在外层有存储结果的对象,这里就不用return
    22             return result;
    23         });
    24     });
    25     return _queue;
    26 }
    27 
    28 queue(p1, p2).then(res => {
    29     console.log(res); // [1, 2]
    30 })

    async/await法

     1 function p1() {
     2     return new Promise((resolve, reject) => {
     3         resolve(1);
     4     }).then(() => {
     5         return "ok";
     6     })
     7 }
     8 
     9 function p2() {
    10     return new Promise((resolve, reject) => {
    11         resolve(2);
    12     })
    13 }
    14 
    15 async function exec() {
    16     // ... 前置处理
    17     let result = [];
    18     console.log("执行p1")
    19     let res1 = await p1();
    20     console.log("执行p2");
    21     let res2 = await p2();
    22     // ... 若干promise
    23     result.push(res1, res2);
    24     return Promise.resolve(result);
    25 }
    26 
    27 exec().then(res => {
    28     console.log(res); // ["ok", 2]
    29 });
    30 
    31 /**
    32  * 注意:此处的代码并不会等exec()函数执行结束后才执行
    33  * 因为在exec()中执行的Promise,一经发出会立即执行,then中的处理函数进入微任务队列,等宏任务执行完后,
    34  * 再来执行微任务队列中的所有函数,如此反复。所以此处的代码在第一个Promise发出后,就会执行。
    35  * 因为此文分享 [Promise顺序执行],所以不过多谈及这个,但还是提一下吧。36  */
    37 console.log("乱入");

    这样也可以:

     1 function p1() {
     2     return new Promise((resolve, reject) => {
     3         resolve(1);
     4     }).then(() => {
     5         return "ok";
     6     })
     7 }
     8 
     9 function p2() {
    10     return new Promise((resolve, reject) => {
    11         resolve(2);
    12     })
    13 }
    14 
    15 async function exec(...t) {
    16     // ... 前置处理
    17     let result = [];
    18     for (let p of t) {
    19         let res = await p();
    20         result.push(res);
    21     }
    22     return Promise.resolve(result);
    23 }
    24 
    25 exec(p1, p2).then(res => {
    26     console.log(res); // ["ok", 2]
    27 });

    带参数

    链式执行法

     1 function p1(id) {
     2     return new Promise((resolve, reject) => {
     3         resolve(id);
     4     })
     5 }
     6 
     7 function queue(ids) {
     8     // ... 前置处理
     9     let result = [];
    10     let _queue = Promise.resolve();
    11     ids.forEach(function(id) {
    12         _queue = _queue.then(() => {
    13             // 只有这样,后面那个then才可以获取到p1的执行结果
    14             return p1(id);
    15         }).then(res => {
    16             result.push(res);
    17             return result;
    18         })
    19     })
    20     return _queue;
    21 }
    22 
    23 queue([1, 2, 3]).then(res => {
    24     console.log(res); // [1, 2, 3]
    25 })

    这样也可以:

     1 function p1(id) {
     2     return new Promise((resolve, reject) => {
     3         resolve(id);
     4     })
     5 }
     6 
     7 function queue(ids) {
     8     // ... 前置处理
     9     let result = [];
    10     let _queue = Promise.resolve();
    11     ids.forEach(function(id) {
    12         _queue = _queue.then(() => p1(id).then(res => {
    13             result.push(res);
    14             return result;
    15         }));
    16     })
    17     return _queue;
    18 }
    19 
    20 queue([1, 2, 3]).then(res => {
    21     console.log(res); // [1, 2, 3]
    22 })

    async/await法

     1 function p1(id) {
     2     return new Promise((resolve, reject) => {
     3         resolve(id);
     4     })
     5 }
     6 
     7 async function exec(...ids) {
     8     // ... 前置处理
     9     let result = [];
    10     for (let id of ids) {
    11         let res = await p1(id);
    12         result.push(res);
    13     }
    14     return Promise.resolve(result);
    15 }
    16 
    17 exec(1, 2).then(res => {
    18     console.log(res); // [1, 2]
    19 });
  • 相关阅读:
    Create方法失效而没有提示错误信息
    JS弹出窗口控制
    本周活动
    JavaScript的初步了解
    关于PHP接收文件的资料
    mvc模式改进网站结构
    一周动态
    排序
    Java的内存泄漏
    Android笔记
  • 原文地址:https://www.cnblogs.com/cone/p/13736119.html
Copyright © 2020-2023  润新知