闲谈Promise

news2024/10/25 5:25:07

预备知识

  • 回调函数:当一个函数作为参数传入另一个函数中,并且它不会立刻执行,当满足一定条件之后,才会执行,这种函数称为回调函数。比如:定时器。
  • 异步任务:与之对应的概念是同步任务,同步任务是在主线程上排队执行,当前面的任务执行完成,才会执行下一个任务。异步任务不进入主线程,而是进入异步队列,前一个任务是否执行完成不影响下一个任务的指向。简单理解就是同步要按代码顺序执行,异步不按照代码顺序执行,异步的执行效率更高。

为什么出现Promise

存在异步任务的代码,不能保证代码按照顺序执行,但在特定的需要下,就是需要在异步中实现顺序执行,这时常使用回调函数去实现,比如下面的代码:

setTimeout(()=>{
            console.log('找实习');
            setTimeout(()=>{
                console.log('面试通过');
                setTimeout(()=>{
                    console.log('拿offer');
                    setTimeout(()=>{
                        console.log('上班');
                    },2000)
                },1000)
            },1000)
        },2000)

执行结果:

虽然上面的代码能实现我们想要的结果,但一些情形下,需要嵌套更多回调函数时,多层嵌套让代码可读性非常差,后期的维护或者异常处理等都变得特别繁琐,让缩进格式也变得非常麻烦。

回调函数A中嵌套回调函数B,回调函数B中嵌套回调函数C.......这种回调函数多层嵌套的情况被称为回调地狱。回调地狱就是为了实现在异步任务中代码也能顺序执行而出现的一种操作。

为解决回调地狱带来的问题,ES6新增了Promise类,让我们能更优雅的书写复杂的异步任务。

Promise

先用一段代码认识一下Promise:

new Promise((resolve,reject)=>{
            setTimeout(()=>{
                resolve('3秒后执行')
            },3000)
}).then(res=>{console.log(res);})
  • 是一个类,需要使用new Promise来创建实例对象。
  • promise有三种状态:pending(待定),fulfilled(已兑现),rejected(已拒绝)。fulfilled和rejected也可以称为已敲定。promise初始状态是pending,promise的状态转换有两条路:一条pending->fulfilled,一条pending->rejected。状态一旦改变,就不能再发生变化。
  • 调用resolve()方法,pending状态会变成fulfilled状态,并且触发then()中第一个回调方法;调用reject()方法,pending状态会变成rejected状态,并且触发then()中第二个回调方法。
  • promise有三个实例方法,then、catch、finally。其中catch和finally实际都是在调用then方法,只是它们往then中传递的参数不一样。
    catch : then(undefined,reject的回调方法)
    finally : then(A回调,A回调)
  • promise的三个实例方法和六个静态方法都是返回一个新的promise。六个静态方法为:resolve、reject、race、all、allSettled、any。其中race、all、allSettled、any将一个 Promise 可迭代对象作为输入(也可以简单理解成:传递数组作为参数)。

promise的实例方法

下面会对三个实例方法进行重写,对于相同的代码进行了提取:

      // 将方法放到任务队列中的方法
      function runAsynctask(callback) {
        if (typeof queueMicrotask === "function") {
          queueMicrotask(callback);
        } else if (typeof MutationObserver === "function") {
          // 创建观察器
          const obs = new MutationObserver(callback);
          // 创建元素,添加监听
          const divNode = document.createElement("div");
          // 参数1 观察的dom节点
          // 参数2 观察的选项(childList 观察子节点改变)
          obs.observe(divNode, { childList: true });
          // 修改元素内容
          divNode.innerText = "999999";
        } else {
          setTimeout(callback, 0);
        }
      }


      // 对then不同的返回值进行不同操作
      function judgmentFn(x, p, resolve, reject) {
        if (x === p) {
          throw new TypeError("Chaining cycle detected for promise #<Promise>");
        }
        if (x instanceof QPromise) {
          x.then(
            (res) => resolve(res),
            (err) => reject(err)
          );
        } else {
          resolve(x);
        }
      }
then方法

​then() 方法最多接受两个参数:用于 Promise 兑现和拒绝情况的回调函数。它返回一个 Promise 对象。

手写then方法:

    then(onFulfilled, onRejected) {
          // 参数判断
          onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (x) => x;
          onRejected = typeof onRejected === "function" ? onRejected : (x) => {throw x;};

          const p = new QPromise((resolve, reject) => {
            // 执行方法
            if (this.state === FULFILLED) {
              runAsynctask(() => {
                try {
                  const x = onFulfilled(this.result);
                  judgmentFn(x, p, resolve, reject);
                } catch (error) {
                  reject(error);
                }
              });
            } else if (this.state === REJECTED) {
              runAsynctask(() => {
                try {
                  const x = onRejected(this.result);
                  judgmentFn(x, p, resolve, reject);
                } catch (error) {
                  reject(error);
                }
              });
            } else if (this.state === PENDING) {
              // 保存回调函数
              this.#handlers.push({
                onFulfilled: () => {
                  runAsynctask(() => {
                    try {
                      const x = onFulfilled(this.result);
                      judgmentFn(x, p, resolve, reject);
                    } catch (error) {
                      reject(error);
                    }
                  });
                },
                onRejected: () => {
                  runAsynctask(() => {
                    try {
                      const x = onRejected(this.result);
                      judgmentFn(x, p, resolve, reject);
                    } catch (error) {
                      reject(error);
                    }
                  });
                },
              });
            }
          });

          return p;
    }
catch方法

catch() :在 promise 被拒绝时调用catch()里的函数;返回一个 Promise 对象。此方法是 Promise.prototype.then(undefined, onRejected) 的一种简写形式。

 catch(onRejected) {
          // 内部调用then方法
          return this.then(undefined, onRejected);
}
finally方法

finally() :用于注册一个在 promise 敲定(兑现或拒绝)时调用的函数,无论是兑现还是拒绝,都是调用同一个函数。

 finally(onFinally) {
          return this.then(onFinally, onFinally);
 }

promise的静态方法

resolve方法

Promise.resolve() :将给定的值转换为一个 Promise。如果这个值本身就是promise,则直接返回这个值(就算这个promise的状态是已拒绝的);其它值就封装成promise,返回的 Promise 将会以该值兑现。

static resolve(value) {
          // 如果是promise 直接返回
          if (value instanceof QPromise) {
            return value;
          }
          // 其他值,就直接封装成promise返回
          return new QPromise((res) => {
            res(value);
          });
}
reject方法

reject():返回一个已拒绝的 Promise 对象,拒绝原因 是给定的参数。

static reject(value) {
          // 不管是什么值(包括 Promise 对象),都重新封装成promise返回
          return new QPromise((undefined, reject) => {
            reject(value);
          });
}
race方法

race():等待第一个敲定;返回一个 Promise,这个返回的 promise 会随着第一个 promise 的敲定而敲定。

static race(promises) {
          // 返回promise
          return new QPromise((resolve, reject) => {
            // 判断是否为数组
            if (!Array.isArray(promises)) {
              return reject(new TypeError("Argument is not iterable"));
            }
            // 等待第一个敲定(promise状态的敲定)
            promises.forEach((p) => {
              // 对数组中的每一项使用resolve,可以保证每一项都是promise,所以每一项都可以使用then
              QPromise.resolve(p).then(
                (res) => {
                  resolve(res);
                },
                (err) => {
                  reject(err);
                }
              );
            });
          });
}
allSettled方法

 allSettled():等待全部敲定;当数组中的每一个都已敲定时,返回的 Promise 将被兑现,并带有描述每个 Promise 结果的对象数组。

   static allSettled(promises) {
          // 返回promise
          return new QPromise((resolve, reject) => {
            // 判断是否为数组
            if (!Array.isArray(promises)) {
              return reject(new TypeError("Argument is not iterable"));
            }
            // 空数组直接兑现
            promises.length === 0 && resolve(promises);

            // 等待全部敲定
            // 记录结果
            const results = [];
            // 记录兑现次数
            let count = 0;
            promises.forEach((p, index) => {
              // 对数组中的每一项使用resolve,可以保证每一项都是promise,所以每一项都可以使用then
              QPromise.resolve(p).then(
                (res) => {
                  // 用索引来添加元素,保证结果顺序和promise数组的顺序一致
                  results[index] = { status: FULFILLED, value: res };
                  // 判断全部兑现
                  count++;
                  // 通过兑现的次数进行判断,保证获取到所有的结果
                  count === promises.length && resolve(results);
                },
                (err) => {
                  results[index] = { status: REJECTED, reason: err };
                  count++;
                  count === promises.length && resolve(results);
                }
              );
            });
          });
        }
all方法

all():两种情况:

  • 当所有输入的 Promise 都被兑现时,返回的 Promise 也将被兑现(即使传入的是空数组),并返回一个包含所有兑现值的数组。
  • 如果输入的任何 Promise 被拒绝,则返回的 Promise 将被拒绝,并带有第一个被拒绝的原因。
    static all(promises) {
          // 返回promise
          return new QPromise((resolve, reject) => {
            // 判断是否为数组
            if (!Array.isArray(promises)) {
              return reject(new TypeError("Argument is not iterable"));
            }
            // 空数组直接兑现
            promises.length === 0 && resolve(promises);

            // 处理全部兑现
            // 记录结果
            const results = [];
            // 记录兑现次数
            let count = 0;
            promises.forEach((p, index) => {
              // 对数组中的每一项使用resolve,可以保证每一项都是promise,所以每一项都可以使用then
              QPromise.resolve(p).then(
                (res) => {
                  // 用索引来添加元素,保证结果顺序和promise数组的顺序一致
                  results[index] = res;
                  // 判断全部兑现
                  count++;
                  // 通过兑现的次数进行判断,保证获取到所有的结果
                  count === promises.length && resolve(results);
                },
                (err) => {
                  // 处理第一个拒绝
                  reject(err);
                }
              );
            });
          });
        }
any方法

any():两种情况:

  • 当输入的任何一个 Promise 兑现时,这个返回的 Promise 将会兑现,并返回第一个兑现的值。
  • 当所有输入 Promise 都被拒绝(包括空数组)时,它会以一个包含拒绝原因数组的AggregateError 拒绝。
  static any(promises) {
          // 返回promise
          return new QPromise((resolve, reject) => {
            // 判断是否为数组
            if (!Array.isArray(promises)) {
              return reject(new TypeError("Argument is not iterable"));
            }
            // 空数组直接兑现
            promises.length === 0 && reject(new AggregateError(promises,'All promises were rejected'))
            // 等待结果
            const errors=[]
            let count=0
            promises.forEach((p,index)=>{
              QPromise.resolve(p).then(res=>{
                // 第一个兑现
                resolve(res)
              },err=>{
                // 全部拒绝
                errors[index]=err
                count++
                count===promises.length && reject(new AggregateError(errors,'All promises were rejected'))
              })
            })
          });
        }

手写Promise

手写promise的完整代码

// 三个状态
      const PENDING = "pending";
      const FULFILLED = "fulfilled";
      const REJECTED = "rejected";

     
      // 定义QPromise类
      class QPromise {
        // 初始状态
        state = PENDING;
        // 初始原因
        result = undefined;

        // 定义实例属性
        #handlers = [];

        // 构造函数
        constructor(fn) {
          const resolve = (result) => {
            // 状态不可逆
            if (this.state === PENDING) {
              // 修改状态
              this.state = FULFILLED;

              this.result = result;
              // 调用成功回调
              this.#handlers.forEach(({ onFulfilled }) => {
                onFulfilled(this.result);
              });
            }
          };
          const reject = (result) => {
            // 状态不可逆
            if (this.state === PENDING) {
              // 修改状态
              this.state = REJECTED;
              this.result = result;
              // 调用失败回调
              this.#handlers.forEach(({ onRejected }) => {
                onRejected(this.result);
              });
            }
          };

          try {
            // 执行
            fn(resolve, reject);
          } catch (error) {
            reject(error);
          }
        }

        // then :将方法放到微任务队列中
        then(onFulfilled, onRejected) {
          // 参数判断
          onFulfilled =
            typeof onFulfilled === "function" ? onFulfilled : (x) => x;
          onRejected =
            typeof onRejected === "function"
              ? onRejected
              : (x) => {
                  throw x;
                };

          const p = new QPromise((resolve, reject) => {
            // 执行方法
            if (this.state === FULFILLED) {
              runAsynctask(() => {
                try {
                  const x = onFulfilled(this.result);
                  judgmentFn(x, p, resolve, reject);
                } catch (error) {
                  reject(error);
                }
              });
            } else if (this.state === REJECTED) {
              runAsynctask(() => {
                try {
                  const x = onRejected(this.result);
                  judgmentFn(x, p, resolve, reject);
                } catch (error) {
                  reject(error);
                }
              });
            } else if (this.state === PENDING) {
              // 保存回调函数
              this.#handlers.push({
                onFulfilled: () => {
                  runAsynctask(() => {
                    try {
                      const x = onFulfilled(this.result);
                      judgmentFn(x, p, resolve, reject);
                    } catch (error) {
                      reject(error);
                    }
                  });
                },
                onRejected: () => {
                  runAsynctask(() => {
                    try {
                      const x = onRejected(this.result);
                      judgmentFn(x, p, resolve, reject);
                    } catch (error) {
                      reject(error);
                    }
                  });
                },
              });
            }
          });

          return p;
        }
        // 实例方法
        catch(onRejected) {
          // 内部调用then方法
          return this.then(undefined, onRejected);
        }
        // 实例方法
        finally(onFinally) {
          return this.then(onFinally, onFinally);
        }

        // 静态方法
        static resolve(value) {
          // 如果是promise 直接返回
          if (value instanceof QPromise) {
            return value;
          }
          // 其他值,就直接封装成promise返回
          return new QPromise((res) => {
            res(value);
          });
        }

        static reject(value) {
          // 不管是什么值(包括 Promise 对象),都重新封装成promise返回
          return new QPromise((undefined, reject) => {
            reject(value);
          });
        }

        // 等待第一个敲定
        static race(promises) {
          // 返回promise
          return new QPromise((resolve, reject) => {
            // 判断是否为数组
            if (!Array.isArray(promises)) {
              return reject(new TypeError("Argument is not iterable"));
            }
            // 等待第一个敲定(promise状态的敲定)
            promises.forEach((p) => {
              QPromise.resolve(p).then(
                (res) => {
                  resolve(res);
                },
                (err) => {
                  reject(err);
                }
              );
            });
          });
        }

        // 全部状态为成功,则返回一个数组
        // 若有一个失败,则处理失败
        static all(promises) {
          // 返回promise
          return new QPromise((resolve, reject) => {
            // 判断是否为数组
            if (!Array.isArray(promises)) {
              return reject(new TypeError("Argument is not iterable"));
            }
            // 空数组直接兑现
            promises.length === 0 && resolve(promises);

            // 处理全部兑现
            // 记录结果
            const results = [];
            // 记录兑现次数
            let count = 0;
            promises.forEach((p, index) => {
              QPromise.resolve(p).then(
                (res) => {
                  // 用索引来添加元素,保证结果顺序和promise数组的顺序一致
                  results[index] = res;
                  // 判断全部兑现
                  count++;
                  // 通过兑现的次数进行判断,保证获取到所有的结果
                  count === promises.length && resolve(results);
                },
                (err) => {
                  // 处理第一个拒绝
                  reject(err);
                }
              );
            });
          });
        }

        // 等待全部状态敲定,不管是失败还是成功状态,都放在一个数组中返回
        static allSettled(promises) {
          // 返回promise
          return new QPromise((resolve, reject) => {
            // 判断是否为数组
            if (!Array.isArray(promises)) {
              return reject(new TypeError("Argument is not iterable"));
            }
            // 空数组直接兑现
            promises.length === 0 && resolve(promises);

            // 等待全部敲定
            // 记录结果
            const results = [];
            // 记录兑现次数
            let count = 0;
            promises.forEach((p, index) => {
              QPromise.resolve(p).then(
                (res) => {
                  // 用索引来添加元素,保证结果顺序和promise数组的顺序一致
                  results[index] = { status: FULFILLED, value: res };
                  // 判断全部兑现
                  count++;
                  // 通过兑现的次数进行判断,保证获取到所有的结果
                  count === promises.length && resolve(results);
                },
                (err) => {
                  results[index] = { status: REJECTED, reason: err };
                  count++;
                  count === promises.length && resolve(results);
                }
              );
            });
          });
        }

        // 返回第一个状态兑现(成功)的结果
        // 全部拒绝时,返回拒绝的结果数组
        static any(promises) {
          // 返回promise
          return new QPromise((resolve, reject) => {
            // 判断是否为数组
            if (!Array.isArray(promises)) {
              return reject(new TypeError("Argument is not iterable"));
            }
            // 空数组直接兑现
            promises.length === 0 && reject(new AggregateError(promises,'All promises were rejected'))
            // 等待结果
            const errors=[]
            let count=0
            promises.forEach((p,index)=>{
              QPromise.resolve(p).then(res=>{
                // 第一个兑现
                resolve(res)
              },err=>{
                // 全部拒绝
                errors[index]=err
                count++
                count===promises.length && reject(new AggregateError(errors,'All promises were rejected'))
              })
            })
          
          
          
          
          });
        }
      }
        
        // 异步函数
      function runAsynctask(callback) {
        if (typeof queueMicrotask === "function") {
          queueMicrotask(callback);
        } else if (typeof MutationObserver === "function") {
          // 创建观察器
          const obs = new MutationObserver(callback);
          // 创建元素,添加监听
          const divNode = document.createElement("div");
          // 参数1 观察的dom节点
          // 参数2 观察的选项(childList 观察子节点改变)
          obs.observe(divNode, { childList: true });
          // 修改元素内容
          divNode.innerText = "999999";
        } else {
          setTimeout(callback, 0);
        }
      }


      // 对then不同的返回值进行不同操作
      function judgmentFn(x, p, resolve, reject) {
        if (x === p) {
          throw new TypeError("Chaining cycle detected for promise #<Promise>");
        }
        if (x instanceof QPromise) {
          x.then(
            (res) => resolve(res),
            (err) => reject(err)
          );
        } else {
          resolve(x);
        }
      }

如果本文对你有帮助,希望能得到你的点赞或收藏或关注,这是对我最好的鼓励;

如你有问题或疑惑,欢迎在评论区写下,必将努力解答;

如本文有误区,希望你不吝赐教,让我们共勉!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2210917.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JVM】面试篇

1 什么是JVM&#xff1f; 1.1 定义 JVM 指的是Java虚拟机&#xff08; Java Virtual Machine &#xff09;。JVM 本质上是一个运行在计算机上的程序&#xff0c;他的职责是运行Java字节码文件&#xff0c;Java虚拟机上可以运行Java、Kotlin、Scala、Groovy等语言。 启动这个程…

电子电气架构---软件定义汽车的新兴生态系统

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消耗你的人和事&#xff0c;多看一眼都是你的不…

【含文档】基于Springboot+Vue的校园体育器材管理系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…

C++ : STL容器之vector剖析

STL容器之vector剖析 一、构造函数与赋值&#xff08;一&#xff09;默认构造&#xff08;二&#xff09;拷贝构造&#xff08;三&#xff09;几个相同值构造&#xff08;四&#xff09;迭代器构造&#xff08;五&#xff09;initializer_list 构造&#xff08;六&#xff09;赋…

网络编程(19)——C++使用asio协程实现并发服务器

十九、day19 上一节学习了如果通过asio协程实现一个简单的并发服务器demo&#xff08;官方案例&#xff09;&#xff0c;今天学习如何通过asio协程搭建一个比较完整的并发服务器。 主要实现了AsioIOServicePool线程池、逻辑层LogicSystem、粘包处理、接收协程、发送队列、网络…

C语言入门:打开编程世界的大门

一.C语言是什么 在我们生活中&#xff0c;我们在交流时候使用的就是语言&#xff0c;在这个世界上有许多的国家、民族&#xff0c;自然也有很多语言如&#xff1a;汉语、英语、法语等等&#xff0c;这种人与人交流使用的语言我们称为自然语言。然而计算机并不能理解我们的语言…

github下载文件的两种方式(非git形式)

1.以下面的图为例 &#xff0c;可以直接点击右上方的绿色Code按键&#xff0c;在弹出的列表中选择Download Zip选项&#xff0c;即可下载。 2.如果下载的是单独的某一个文件&#xff0c;则可以按照下图的格式点击下图所示的那个下载的图标即可。

【Linux系统编程】第三十一弹---深入理解静态库:从零开始制作与高效使用的完全指南

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、静态库 1.1、怎么做静态库 1.2、怎么使用静态库 1、静态库 1.1、怎么做静态库 在Linux环境下&#xff0c;通常使用GCC&am…

【2024最新】基于springboot+vue的实验室管理系统lw+ppt

作者&#xff1a;计算机搬砖家 开发技术&#xff1a;SpringBoot、php、Python、小程序、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;Java精选实战项…

PAT甲级-1034 Head of a Gang

题目 题目大意 一个犯罪团伙满足条件&#xff1a;人数 > 2&#xff1b;团伙内的总通话时长 > k。团伙首领就是该团伙中通话时长最多的。先给定一组通话&#xff0c;格式为 A B time&#xff0c;要求输出犯罪团伙的数目&#xff0c;并输出每个团伙的首领名字和该团伙的人…

一文详解数据库范式

背景 在开发中&#xff0c;我们经常需要考虑如何设计合适的表结构&#xff0c;而则往往需要考虑数据库的范式。数据库的三范式&#xff08;3NF&#xff09;是数据库设计过程中用来减少数据冗余和提高数据一致性的重要规则。它们分别是第一范式&#xff08;1NF&#xff09;、第二…

【PR小技巧】PR技术分享 一 PR关键帧小技巧介绍

在Adobe Premiere Pro (简称PR) 中&#xff0c;关键帧是用于控制视频剪辑、音频轨道、效果动画等随时间变化的重要工具。通过合理使用关键帧&#xff0c;可以实现各种复杂的动画效果和精确的时间控制。今天我们就来学习一些关于关键帧的小技巧&#xff0c;以及具体的例子来说明…

算法专题五: 位运算

目录 常见位运算总结1. 位1的个数2. 比特位计数3. 汉明距离4. 只出现一次的数字5. 只出现一次的数字Ⅲ6. 判定字符是否唯一7. 丢失的数字8. 两正数之和9. 只出现一次的数字Ⅲ10. 消失的两个数字 常见位运算总结 重点 : 1. 位1的个数 算法思路: 这道题就用到了我们总结的那个第…

全新YOLOv11美化版检测界面 涵盖超多功能 支持百种模型改进训练

文章目录 前言视频效果必要环境一、界面功能概述1. 运行方法2. 图像选择图像:表格信息:统计信息:IOU和NMS调节:目标框显示: 3. 文件夹选择文件夹:进度显示:推理结果: 4. 视频、摄像头进度显示:实时检测:帧状态回溯: 5. 替换界面中的模型5. 鼠标悬浮 二、训练改进模型运行方法假…

力扣周赛:第419场周赛

&#x1f468;‍&#x1f393;作者简介&#xff1a;爱好技术和算法的研究生 &#x1f30c;上期文章&#xff1a;力扣周赛&#xff1a;第415场周赛 &#x1f4da;订阅专栏&#xff1a;力扣周赛 希望文章对你们有所帮助 因为一些特殊原因&#xff0c;这场比赛就打了1h&#xff0c…

[Linux] Linux 模拟实现 Shell

标题&#xff1a;[Linux] Linux 模拟实现 Shell 个人主页水墨不写bug&#xff08;图片来源于网络&#xff09; 目录 一、什么是shell 二、shell的理解 三、模拟实现shell 1&#xff09;打印命令行提示 2&#xff09;获取用户的输入字符串 3&#xff09;分割命令字符串 4…

【优选算法篇】双指针的优雅舞步:C++ 算法世界的浪漫探索

文章目录 C 双指针详解&#xff1a;基础题解与思维分析前言第一章&#xff1a;对撞指针1.1 移动零解题思路图解分析C代码实现易错点提示代码解读 1.2 复写零解题思路算法步骤C代码实现易错点提示代码复杂度 1.3 盛最多水的容器1. 题目链接2. 题目描述解法一&#xff08;暴力求解…

链表(4)_合并K个升序链表_面试题

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 链表(4)_合并K个升序链表_面试题 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录…

第十五届蓝桥杯C++B组省赛

文章目录 1.握手问题解题思路1&#xff08;组合数学&#xff09;解题思路2&#xff08;暴力枚举&#xff09; 2.小球反弹做题思路 3.好数算法思路&#xff08;暴力解法&#xff09;---不会超时 4.R格式算法思路 5.宝石组合算法思路---唯一分解定理 6.数字接龙算法思路----DFS 7…

【Oracle数据库进阶】001.SQL基础查询_查询语句

课 程 推 荐我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448;入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448;虚 拟 环 境 搭 建 &#xff1a;&#x1…