8-js高级-6(promise)

一 Promise 的理解和使用

1 Promise 是什么?

理解

抽象表达:

  • Promise 是一门新的技术(ES6 规范)
  • Promise 是 JS 中进行异步编程的新解决方案 (备注:旧方案是单纯使用回调函数)

具体表达:

  • 从语法上来说: Promise 是一个构造函数
  • 从功能上来说: promise 对象用来封装一个异步操作并可以获取其成功/ 失败的结果值

promise 的状态改变

  1. pending 变为 resolved
  2. pending 变为 rejected

**说明: **

只有这 2 种, 且一个 promise 对象只能改变一次

无论变为成功还是失败, 都会有一个结果数据

成功的结果数据一般称为 value, 失败的结果数据一般称为 reason

promise 的基本流程

在这里插入图片描述

promise 的基本使用

  • 使用 1: 基本编码流程
  <script>
        // 1) 创建 promise 对象(pending 状态), 指定执行器函数
        const p = new Promise((resolve, reject) => {
            // 2) 在执行器函数中启动异步任务
            setTimeout(() => {
                const time = Date.now();
                // 3) 根据结果做不同处理
                if (time % 2 == 1) {
                    // 3.1) 如果成功了, 调用 resolve(), 指定成功的 value, 变为 resolved 状态
                    resolve("成功的值" + time);
                } else {
                    // 3.2) 如果失败了, 调用 reject(), 指定失败的 reason, 变为rejected 状态
                    reject("失败的值" + time);
                }
            }, 2000);
        });

        // 4) 能 promise 指定成功或失败的回调函数来获取成功的 vlaue 或失败的 reason
        p.then(
            // 成功的回调函数 onResolved, 得到成功的 vlaue
            value => console.log('成功的 value: ', value),
            // 失败的回调函数 onRejected, 得到失败的 reason
            reason => console.log('失败的 reason: ', reason)
        );
      
    </script>
  • 使用 2: 使用 promise 封装基于定时器的异步
    <script>

        function doDelay(time) {
            return new Promise((resolve, reject) => {

                setTimeout(() => {
                    const now = Date.now();
                    if (now % 2 == 1) {
                        resolve("成功的值" + now);
                    } else {
                        reject("失败的值" + now);
                    }
                }, time);
            });
        }

        const promise = doDelay(2000);
        promise.then(
            value => console.log('成功的 value: ', value),
            reason => console.log('失败的 reason: ', reason)
        );


    </script>
  • 使用 3: 使用 promise 封装 ajax 异步请求
    <script>

        //可复用的发 ajax 请求的函数: xhr + promise
        function promiseAjax(url) {
            return new Promise((resolve, reject) => {
                const xhr = new XMLHttpRequest()
                xhr.onreadystatechange = () => {
                    if (xhr.readyState !== 4) return
                    const { status, response } = xhr
                    // 请求成功, 调用 resolve(value)
                    if (status >= 200 && status < 300) {
                        resolve(JSON.parse(response))
                    } else { // 请求失败, 调用 reject(reason)
                        reject(new Error('请求失败: status: ' + status))
                    }
                }
                xhr.open("GET", url)
                xhr.send()
            })
        }
        promiseAjax('http://152.136.185.210:7878/api/hy66/home/data?type=pop&page=1')
            .then(
                data => {
                    console.log('显示成功数据', data)
                },
                error => {
                    alert(error.message)
                }
            )

    </script>

2 为什么要用 Promise?

指定回调函数的方式更加灵活

  1. 旧的: 必须在启动异步任务前指定

  2. promise: 启动异步任务 => 返回promie对象 => 给promise对象绑定回调函 数(甚至可以在异步任务结束后指定/多个)

支持链式调用, 可以解决回调地狱问题

  1. 什么是回调地狱?

    回调函数嵌套调用, 外部回调函数异步执行的结果是嵌套的回调执行的条件

  2. 回调地狱的缺点?

    不便于阅读 不便于异常处理

  3. 解决方案?

    promise 链式调用

  4. 终极解决方案?

    async/await

    <script>
        // 成功的回调函数
        function successCallback(result) {
            console.log("声音文件创建成功: " + result);
        }
        // 失败的回调函数
        function failureCallback(error) {
            console.log("声音文件创建失败: " + error);
        }
        /* 1.1 使用纯回调函数 */
        createAudioFileAsync(audioSettings, successCallback, failureCallback)

        /* 1.2. 使用 Promise */
        const promise = createAudioFileAsync(audioSettings);
        setTimeout(() => {
            promise.then(successCallback, failureCallback);
        }, 3000);

        /*
        2.1. 回调地狱
        */
        doSomething(function (result) {
            doSomethingElse(result, function (newResult) {
                doThirdThing(newResult, function (finalResult) {
                    console.log('Got the final result: ' + finalResult)
                }, failureCallback)
            }, failureCallback)
        }, failureCallback)
        /*
        2.2. 使用 promise 的链式调用解决回调地狱
        */
        doSomething().then(function (result) {
            return doSomethingElse(result)
        }).then(function (newResult) {
            return doThirdThing(newResult)
        }).then(function (finalResult) {
            console.log('Got the final result: ' + finalResult)
        }).catch(failureCallback)
        /*
        2.3. async/await: 回调地狱的终极解决方案
        */
        async function request() {
            try {
                const result = await doSomething()
                const newResult = await doSomethingElse(result)
                const finalResult = await doThirdThing(newResult)
                console.log('Got the final result: ' + finalResult)
            } catch (error) {
                failureCallback(error)
            }
        }

    </script>

如何使用 Promise?

API

  1. Promise 构造函数: Promise (excutor) {}
    • executor 函数: 执行器 (resolve, reject) => {}
    • resolve 函数: 内部定义成功时我们调用的函数 value => {}
    • reject 函数: 内部定义失败时我们调用的函数 reason => {}
    • 说明: executor 会在 Promise 内部立即同步调用,异步操作在执行器中执行
  2. Promise.prototype.then 方法: (onResolved, onRejected) => {}
    • onResolved 函数: 成功的回调函数 (value) => {}
    • onRejected 函数: 失败的回调函数 (reason) => {}
    • 说明: 指定用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调
    • 返回一个新的 promise 对象
  3. Promise.prototype.catch 方法: (onRejected) => {}
    • onRejected 函数: 失败的回调函数 (reason) => {}
    • 说明: then()的语法糖, 相当于: then(undefined, onRejected)
  4. Promise.resolve 方法: (value) => {}
    • value: 成功的数据或 promise 对象
    • 说明: 返回一个成功/失败的 promise 对象
    • 说明: 当value为失败的promise对象时则返回一个失败的promise
  5. Promise.reject 方法: (reason) => {}
    • reason: 失败的原因
    • 说明: 返回一个失败的 promise 对象
  6. Promise.all 方法: (promises) => {}
    • promises: 包含 n 个 promise 的数组
    • 说明: 返回一个新的 promise, 只有所有的 promise 都成功才成功, 只要有一个失败了就 直接失败
  7. Promise.race 方法: (promises) => {}
    • promises: 包含 n 个 promise 的数组
    • 说明: 返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态

promise 的几个关键问题

  1. 如何改变 promise 的状态?
    • resolve(value): 如果当前是 pending 就会变为 resolved
    • reject(reason): 如果当前是 pending 就会变为 rejected
    • 抛出异常: 如果当前是 pending 就会变为 rejected
  2. 一个 promise 指定多个成功/失败回调函数, 都会调用吗?
    • 当 promise 改变为对应状态时都会调用
  3. 改变 promise 状态和指定回调函数谁先谁后?
    • 都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调
    • 如何先改状态再指定回调?
      • 在执行器中直接调用 resolve()/reject()
      • 延迟更长时间才调用 then()
    • 什么时候才能得到数据?
      • 如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
      • 如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据
  4. promise.then()返回的新 promise 的结果状态由什么决定?
    • 简单表达: 由 then()指定的回调函数执行的结果决定
    • 详细表达:
      • 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常
      • 如果返回的是非 promise 的任意值, 新 promise 变为 resolved, value 为返回的值
      • 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果
  5. promise 如何串连多个操作任务?
    • promise 的 then()返回一个新的 promise, 可以开成 then()的链式调用
    • 通过 then 的链式调用串连多个同步/异步任务
  6. promise 异常传透?
    • 当使用 promise 的 then 链式调用时, 可以在最后指定失败的回调,
    • 前面任何操作出了异常, 都会传到最后失败的回调中处理
  7. 中断 promise 链?
    • 当使用 promise 的 then 链式调用时, 在中间中断, 不再调用后面的回调函数
    • 办法: 在回调函数中返回一个 pendding 状态的 promise 对象

二 async 与 await

定义

async 是异步的意思,await则可以理解为 async wait。所以可以理解async就是用来声明一个异步方法,而 await是用来等待异步方法执行

async作为一个关键字放在函数前面,表示该函数是一个异步函数,异步函数意味着该函数的执行不会阻塞后面代码的执行;而 await 用于等待一个异步方法执行完成;

async/await的作用就是使异步操作以同步的方式去执行

1 关于async

async的用法,语法很简单,在函数前面加上async关键字,表示函数是异步的。

 async function timeout() {
     return 'hello world!'
 }

只有一个作用,他的调用会返回一个promise对象。

那怎么调用呢?async 函数也是函数,平时我们怎么使用函数就怎么使用它,直接加括号调用就可以了,为了表示它没有阻塞它后面代码的执行,我们在async 函数调用之后加一句console.log;

 async function timeout() {
     return 'hello world!'
 }
 timeout()
 console.log('我虽然在后面,但是先执行')

打印结果:

在这里插入图片描述

发现 timeout() 函数虽然调用了,但是没打印 hello world!; 先不要着急, 看一看timeout() 返回了什么? 把上面的 timeout() 语句改为console.log(timeout())

打印结果:

在这里插入图片描述

原来async 函数返回的是一个promise 对象,并且Promise还有state和result,如果async函数中有返回值,当调用该函数时,内部会调用Promise.resolve()方法把它转化成一个promise对象作为返回,但如果timeout函数内部抛出错误呢? 那么就会调用Promise.reject() 返回一个promise 对象

async function timeout() {
    throw new Error('rejected');
}
console.log(timeout());

就会调用Promise.reject() 返回一个promise 对象

在这里插入图片描述

那么要想获取到async 函数的执行结果,就要调用promise的then 或 catch 来给它注册回调函数

继续修改代码

  	async function timeout() {
      return 'hello world!'
    }

    timeout().then(val => {
      console.log(val)
    })

    console.log('我虽然在后面,但是先执行')

在这里插入图片描述

我们获取到了"hello world!', 同时timeout的执行也没有阻塞后面代码的执行,和我们刚才说的一致。

如果async 函数执行完,返回的promise 没有注册回调函数,比如函数内部做了一次for 循环,你会发现函数的调用,就是执行了函数体,和普通函数没有区别,唯一的区别就是函数执行完会返回一个promise 对象

   async function timeout () {
      for (let index = 0; index < 3; index++) {
        console.log('async', +index)
      }
    }
    console.log(timeout())
    console.log('outer')

在这里插入图片描述

另外,async函数返回一个promise对象,下面两种方法是等效的

// 方法1
function f() {
    return Promise.resolve('TEST');
}
// asyncF is equivalent to f!

// 方法2
async function asyncF() {
    return 'TEST';
}

2 关于await

await 到底在等啥?

async 关键字差不多了,最重要的就是async函数的执行会返回promise对象,并且把内部的值进行promise的封装。如果promise对象通过then或catch方法又注册了回调函数,async函数执行完以后,注册的回调函数就会放到异步队列中,等待执行。

如果只是async,和promise差不多,但有了await就不一样了,await关键字只能放到async函数里面,await是等待的意思,那么它等待什么呢?它后面跟着什么呢?其实await不仅仅用于等Promise对象,还可以等任意表达式,所以await后面实际是可以接普通函数调用或者直接量的,不过我们更多的是放一个返回promise 对象的表达式。他等待的是promise对象执行完毕,并返回结果。

//所以下面这个示例完全可以正确运行
    function getSomething () {
      return 'something'
    }
    async function testAsync () {
      return Promise.resolve('hello async')
    }
    async function test () {
      const v1 = await getSomething()
      const v2 = await testAsync()
      console.log(v1, v2)
    }
    test()

await 等到了要等的,然后呢?

await 等到了它要等的东西,一个 Promise 对象,或者其它值,然后呢?

  1. 如果它等到的不是一个Promise对象,那么await表达式的运算结果就是它等到的东西。
  2. 如果它等到的是一个Promise对象,await就忙起来了,它会阻塞函数后面的代码,等着Promise对象resolve,然后得到resolve的值,作为await表达式的运算结果。

async/await 帮我们干了啥?

做个简单的比较
现在举例,用 setTimeout 模拟耗时的异步操作,先来看看不用 async/await 会怎么写

function takeLongTime () {
      return new Promise(resolve => {
        setTimeout(() =>
          resolve('long_time_value'), 1000
        )
      })
    }
takeLongTime().then(val => {
   console.log(val, 'val')
})

如果改用 async/await 呢,会是这样

    function takeLongTime () {
      return new Promise(resolve => {
        setTimeout(() =>
          resolve('long_time_value'), 1000
        )
      })
    }
     async function test () {
      let v = await takeLongTime()
      console.log(v, 'v')
    }
    test()

眼尖的已经发现 takeLongTime () 没有申明为async。实际上takeLongTime () 本身就返回Promise对象,加不加async结果都一样。

await 优势在于处理 then 链,使代码看起来像同步代码一样,下面是实例应用

现在写一个函数,让它返回promise 对象,该函数的作用是2s 之后让数值乘以2

// 2s 之后返回双倍的值
function doubleAfter2seconds (num) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(num * 2)
        }, 2000)
      })
    }

现在再写一个async 函数,从而可以使用await 关键字, await 后面放置的就是返回promise对象的一个表达式,所以它后面可以写上 doubleAfter2seconds 函数的调用

async function testResult() {
    let result = await doubleAfter2seconds(30);
    console.log(result); //2s后打印60
}
testResult();

代码的执行过程

调用testResult 函数,它里面遇到了await, await 表示等待,代码就暂停到这里,不再向下执行了,它等待后面的promise对象执行完毕,然后拿到promise resolve 的值并进行返回,返回值拿到之后,它继续向下执行。具体到 我们的代码, 遇到await 之后,代码就暂停执行了, 等待doubleAfter2seconds(30) 执行完毕,doubleAfter2seconds(30) 返回的promise 开始执行,2秒 之后,promise resolve 了, 并返回了值为60, 这时await 才拿到返回值60, 然后赋值给result, 暂停结束,代码继续执行,执行 console.log语句。

就这一个函数,我们可能看不出async/await 的作用,如果我们要计算3个数的值,然后把得到的值进行输出呢?

async function testResult() {
    let first = await doubleAfter2seconds(30);
    let second = await doubleAfter2seconds(50);
    let third = await doubleAfter2seconds(30);
    console.log(first + second + third);
}
testResult()

6秒后,控制台输出220, 我们可以看到,写异步代码就像写同步代码一样了,再也没有回调地域了。

这里强调一下,当js引擎在等待promise.resolve的时候,他并没有真正的暂停工作,它可以处理其他的一些事情,如果我们在testResult函数后面继续执行其他代码,比如console.log一下,会发现console.log代码先执行。

async function testResult() {
    let first = await doubleAfter2seconds(30);
    let second = await doubleAfter2seconds(50);
    let third = await doubleAfter2seconds(30);
    console.log(first + second + third);
}
testResult()
console.log('我先执行!!!')

先输出 “我先执行!!!”,6s后输出计算结果。

在这里插入图片描述

3 举例

当遇到 await 时,会阻塞函数内部处于它后面的代码(而非整段代码),去执行该函数外部的同步代码;当外部的同步代码执行完毕,再回到该函数执行剩余的代码。并且当 await 执行完毕之后,会优先处理微任务队列的代码。

 <script>
        async function fn1() {
            console.log(1)
            const value = await fn2() // fn2进入微任务队列等待执行
            console.log(value)
            console.log(2) // 阻塞
        }
        async function fn2() {
            console.log('fn2')
            return 666;
        }
        fn1()
        console.log(3)
    </script>

    // 结果:1 fn2 3 666 2
    // 痛点:
    // 执行fn2()后返回一个成功状态且值为666的promise,该promise的then的回调进入微任务队列等待执行
    // await 会阻塞它下面的代码,先执行 async 外面的同步代码
    // 同步代码执行完后,执行异步任务(当前为微任务队列中得promise的then的回调)
    // 释放了async函数中的await的阻塞,使得其后的代码得到执行

4 总结:

  1. async 函数
    1)函数的返回值为Promise对象
    2)Promise对象的结果由async函数执行的返回值决定
  2. await 表达式
    1)正常情况下,await右侧的表达式一般为 promise对象 , 但也可以是其它的值
    2)如果表达式是promise对象,await就忙起来了,它会阻塞函数后面的代码,等着Promise对象resolve,然后得到resolve的值,作为await表达式的运算结果。
    3)如果表达式是其它值, 直接将此值作为await的返回值
  3. asyncawait基于promise的。使用async的函数将会始终返回一个 promise 对象。这一点很重要,要记住,可能是你遇到容易犯错的地方。
  4. 在使用await的时候我们只是暂停了函数,而非整段代码。这里经常会是容易犯错的地方。
  5. async和await是非阻塞的
  6. 仍然可以使用 Promise,例如Promise.all(p1, p2, p3).,接受一个数组作为参数,p1、p2、p3 都是 Promise 实例,如果不是,就会先调用 Promise .resolve方法,将参数转为 Promise 实例,再进一步处理。只要 p1、p2、p3 之中有一个被 rejected,整个状态就变成 rejected。
  7. 注意
    1)await必须写在async函数中, 但async函数中可以没有await
    2)如果await的promise失败了, 就会抛出异常, 需要通过try…catch来捕获处理

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

239. 滑动窗口最大值

力扣题目链接 (opens new window) 给定一个数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回滑动窗口中的最大值。 进阶&#xff1a; 你能在线性时间复杂度内解…

根据UIL下载图片/视频、根据URL自动下载图片/视频、GUI自动下载想要的图片

1&#xff0c;根据UIL下载图片/视频 def downForInterface(file_path):count 1value_rows []with open(file_path, encodingUTF-8) as file:f_csv csv.reader(file)for r in f_csv:value_rows.append(r)for file_path in value_rows:cunmulu if . in file_path[0]:print(cu…

[VUE]Element_UI 实现TreeSelect 树形选择器

文章目录 前言1、安装2、引用3、使用 前言 最近在做一个人员管理系统&#xff0c;在增改用户信息时&#xff0c;可能会设置用户所在的部门&#xff0c;因为部门是多级的&#xff0c;于是想到用Element_UI的TreeSelect组件实现 效果&#xff1a; 1、安装 npm install --save…

【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(持久化功能分析)

探究Redis服务启动的过程机制的技术原理和流程分析的指南&#xff08;持久化功能分析&#xff09; Redis提供的持久化机制Redis持久化如何工作Redis持久化的故障分析持久化频率操作分析数据库多久调用一次write&#xff0c;将数据写入内核缓冲区&#xff1f;内核多久将系统缓冲…

网络安全(黑客)学习笔记

1.什么是网络安全&#xff1f; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有…

微服务安全简介

​由于其可扩展性、灵活性和敏捷性&#xff0c;微服务架构已经变得越来越受欢迎。然而&#xff0c;随着这种架构的分布和复杂性增加&#xff0c;确保强大的安全措施变得至关重要。微服务的安全性超越了传统的方法&#xff0c;需要采用全面的策略来保护免受不断演变的威胁和漏洞…

Nginx与Tomcat服务器的区别以及个人网站部署方案

- Nginx和Tomcat作用一样吗&#xff1f; 答&#xff1a;不完全相同。Nginx 和 Tomcat 都可以作为 Web 服务器&#xff0c;但它们的作用略有不同。 Nginx 是一个高性能的 Web 服务器和反向代理服务器。它的主要作用是提供静态文件服务、反向代理、负载均衡、缓存、SSL 加密等功…

从新手到大师:优雅的Vim熟练之旅(万文详解)

从新手到大师&#xff1a;优雅的Vim熟练之旅 博主简介一、前言1.1、Vim编辑器的重要性和流行性1.2、目标 二、Vim简介2.1、什么是Vim2.2、历史和背景简介2.3、Vim的优势和适用场景 三、安装和设置Vim3.1、下载和安装Vim编辑器3.2、基本配置&#xff1a;.vimrc文件的重要性和常用…

解决使用@Field注解配置分词器失效问题(Spring Data Elasticsearch)

问题复现&#xff1a;插入数据时&#xff0c;实体类配置的Field注解没有生效 实体类&#xff1a; package cn.aopmin.pojo;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.data.annotation.Id; import…

网工玩虚拟机,别再只会用VMware了

中午好&#xff0c;我的网工朋友。 说起虚拟机&#xff0c;大家都不陌生吧。 虽然容器技术现在很火爆&#xff0c;但虚拟机还是业内网红。 毕竟使用场景非常多&#xff0c;比如说搭建测试环境、在Windows系统中安装Linux或在Mac机器上运行Windows系统…… 甚至还可以用来进…

jmeter随记2:压测

jmeter随记1:压测 简述一、压测步骤二、观察cpu和内存占用情况三、查看磁盘占用情况 简述 关于压测&#xff0c;jmeter更直观的作用是用来编写压测脚本【请求和压测策略】&#xff0c;然后在linux服务器上执行&#xff0c;也可以在本地执行&#xff0c;压测执行脚本在启动jmet…

深“扒”云原生高性能分布式文件系统JuiceFS

JuiceFS 是一款面向云原生设计的高性能分布式文件系统&#xff0c;在 Apache 2.0 开源协议下发布。提供完备的 POSIX 兼容性&#xff0c;可将几乎所有对象存储接入本地作为海量本地磁盘使用&#xff0c;亦可同时在跨平台、跨地区的不同主机上挂载读写。 JuiceFS 简介 JuiceFS…

C#月数计算器(主要用于社保、医保缴费月数计算)

1、为什么做这个&#xff1f; 工作中&#xff0c;经常需要计算参保人社保、医保缴费月数&#xff0c;之前都是在Excel中写一个DATEDIF公式&#xff0c;修改单元格中的日期&#xff0c;计算间隔的月数&#xff0c;公式如下&#xff1a; DATEDIF(起始日期, 终止日期, 返回类型) …

如何在APP开发中实现无缝用户体验?

我们在日常生活中经常会看到这样一种情况&#xff1a;当我们打开 APP时&#xff0c;有时会出现卡顿、死机的情况&#xff0c;这就是所谓的“死机”现象。在开发 APP时&#xff0c;我们需要考虑用户体验&#xff0c;在用户操作 APP时能够感受到顺畅的使用体验&#xff0c;让用户…

体制内裸辞,她用云端地球实现了自己的乡村梦

追逐田园的“诗与远方” “我最初的梦想&#xff0c;就是有一个亲手打造的、能装进个人喜好的小院子。”为完成自己的梦想&#xff0c;吕春萍毅然放弃了体制内的工作&#xff0c;来到秦岭脚下的桥南镇曹峪村&#xff0c;践行自己的“乡村梦”。 起初&#xff0c;吕春萍做了五…

晚上12点接到面试邀约电话,待业一个月的我却拒绝了....

前言 一位测试朋友最近一直在找工作&#xff0c;前两天刚拒绝了一个面试。那天晚上12点多&#xff0c;他接到一个HR的面试电话&#xff0c;让他第二天早上10点去公司面试。朋友和HR聊了两句&#xff0c;了解到这位HR经常加班&#xff0c;于是果断拒绝了这个面试。 我还为他可惜…

adnroid 11. 0 Activity启动流程图解

从Launcher到ActivityTaskManager 从ActivityTaskManagerService 到 ApplicationThread 从ApplicationThread到onCreate

docker基本命令学习 | Docker网络、Docker镜像发布

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; docker安装、卸载 docker安装使用 卸载旧版本docker或者环境 [rootiZf8zdcobr3fw7vn0p3538Z /]# yum remove docker \ > docker-client \ >…

【Kafka】消息队列Kafka基础

目录 消息队列简介消息队列的应用场景异步处理系统解耦流量削峰日志处理 消息队列的两种模式点对点模式发布订阅模式 Kafka简介及应用场景Kafka比较其他MQ的优势Kafka目录结构搭建Kafka集群编写Kafka一键启动/关闭脚本 Kafka基础操作创建topic生产消息到Kafka从Kafka消费消息使…

计算机网络最基础知识介绍

OSI和TCP/IP是很基础但又非常重要的知识,很多知识点都是以它们为基础去串联的,作为底层,掌握得越透彻,理解上层时会越顺畅。今天这篇网络基础科普,就是根据OSI层级去逐一展开的。 01 计算机网络基础 01 计算机网络的分类 按照网络的作用范围:广域网(WAN)、城域网(MA…