javascript 学习之:异步和 promise 的使用

什么是异步操作

  • 在JavaScript中,异步行为通常是指那些不会立即完成的操作,比如网络请求、文件操作或任何需要等待的操作。为了管理这种异步行为,JavaScript 提供了几种机制,其中 Promise 是非常核心的一个。

异步操作的示例

  • 如果你不知道什么是异步操作,你可以看这个例子:
function operate1() {
    // http 发出请求;等待回复
    ....
    console.log("operate1 finished")
}

function operate2() {
    // http 发出请求;等待回复
    ....
    console.log("operate2 finished")
}

operate1();
operate2();
  • 上述描述了两个函数 operate1()operate2()
  • operate1()operate2() 中都定义了两个网络请求,而网络请求取决于网络情况、服务器那边处理的速度,所以会导致最终这两个函数的结果不知道

什么是 promise

  • Promise 是一个 代表了异步操作最终完成或失败的对象。它可以让你组织异步代码的方式更加清晰,避免所谓的“回调地狱”。这里面涉及了三个概念:
    • promise 是一个对象
    • 这个对象代表了异步操作的 ”完成” 或者 “失败”

为什么要用 promise

  • 一言以蔽之:为了将那些异步的程序,按照顺序地执行。

  • 举个简单的例子,你今天要做以下的事情:

    • 给 A 发送微信消息,
    • 等 A 回复之后你要约 B 吃饭的时间。
    • 等 B 告诉你具体时间之后你需要去洗车
    • 洗碗
    • 刷盘子
  • 你给 A 发了消息之后他一直没回复。这时候如果你是用 同步 的方式在执行。那在 A 回消息之前(这个过程可能要两个小时),你无法执行后面的步骤;这时候用程序表示:

    // 同步操作的程序
    执行一天的事情(){
    	1.A 发送微信消息();
    	2.B 吃饭的时间();
    	3. 洗车();
    	4. 洗碗();
    	5. 洗盘子()
    }
    
  • 如果是异步执行,那么 你把 A 的消息发送出去之后不必等到 A 的回复 你就可以进行后面的步骤

  • 如果写成代码就是:

    // 异步操作的程序
    async 执行一天的事情(){
    	1.A 发送微信消息();
    	2.B 吃饭的时间();
    	3. 洗车();
    	4. 洗碗();
    	5. 洗盘子()
    }
    
  • 因为有了 async 这个关键词,使你的执行变成了 异步 的方式;首先要注意一点:

    • 异步的意思 并不是说,现在 1,2,3,4, 5 可以同时执行了,那不叫 异步,那叫 并发 ;并发和异步的区别在于 异步 是单线程中对效率最大化的追求,而 并发 则是有两个及以上的 线程 或者 进程;同时 异步 程序由于是单线程,所以程序还是从上到下依次执行,但是 并发 定义范围内的程序是可以真正做到 “同时” 执行的。当然并发也分为 真并发伪并发 一旦并发数量超过 cpu 的核数,其实就是 伪并发 而不是 真并发,当然这个不是我们这篇文章关注的内容。
    • 异步的意思是 1,2,3,4, 5 还是会先执行 1, 然后 2, 然后 3,… 但区别是:
      • 之前 同步 的时候,2 必须等 1 完全执行完成了,才能执行,
      • 但现在是只要 给 A 发送微信消息(); 的消息发出去了,不必等到 A 回复就可以执行 约 B 吃饭的时间() 这个操作;这样做的目的是不阻塞整个后面的程序执行。总结成一句话就是:异步是按照代码的顺序触发,但不等待每个函数的执行结果
    • 也就是说,一旦使用 async 来定义函数,函数内部就会以更高效率执行,虽然还是会按照 code 的顺序一行行触发,但每个单独的函数不再等待上一个完成。除非你用 await关键字,那么整个异步程序的焦点就会放到 await 上,等待 await 定义的那一行执行结束。
      async 执行一天的事情(){A 发送微信消息();
      	awaitB 吃饭的时间();
      	洗车();
      	洗碗();
      	洗盘子()
      }
      
    • 但问题又来了。await 只能保证程序运行到 B 这里能够停住,得到 B 的返回结果之后再往下进行,但是并不能保证 A, B 这两个程序之间的顺序。
    • 为了保证多个异步程序之间需要 “按照顺序” 执行,就要引入 promise;也就是说,如果我要保证必须按照 给 A 发送微信并且得到 A 的回复之后才能跟 B 约吃饭时间;并且我还不想阻塞其他的与此 “无关” 的行为执行,即,我想保证程序中部分的操作是 “有序的” 其他单独的操作效率最大化,那么这个时候就需要 promise 的操作(并不是说没有 promise 就无法实现,而是 promise 的引入让这个过程变的很简单)

promise 对象

一个 Promise 对象有三种状态:

  • Pending(进行中): 初始状态,既不是成功,也不是失败状态。

  • Fulfilled(已成功): 意味着操作成功完成。

  • Rejected(已失败): 意味着操作失败。

  • 既然是个对象,在 javascript 中肯定就要用 new 的方式来创建,所以,如果我们要创建一个 promise 的话,一个标准的方式是:

    let promise = new Promise(function(resolve, reject) {
        // 这里是异步执行的部分,可以是任何异步的操作
        setTimeout(() => {
            // 成功执行后调用 resolve()
            resolve("操作成功");
            // 如果有错误或者不想执行成功,调用 reject()
            // reject("发生错误");
        }, 1000);
    });
    
  • 这里你肯定有个问题就是:resolvereject 是什么?

  • 简单来说 resolve 是 promise 中封装的代码逻辑成功运行 完成的标志;而 reject 则是 promise 中的函数逻辑运行 失败的标志

  • 而如果 promise 里面定义的程序还在运行的过程中,promise 对象的状态就是 pending

  • 在上面的程序中,当睡眠 1000 ms 之后,会自动触发 resolve 标志。这个 resolve 标志的作用主要是我们在构建 promise 链时,告诉后面的异步程序 “我这边执行完了,拿到结果了,你可以继续运行了”

promise 链

  • 假设我们对 给 A 发送微信消息();约 B 吃饭的时间(); 这两个 “耗时很长” 的步骤用 promise 定义一下,大概长下面的样子
functionA 发送微信消息() {
    return new Promise(resolve => {
        response = http.post(....)
        resolve(response)
    });
}


functionB 吃饭的时间() {
	return new Promise(resolve => {
	        response = http.post(....)
	        resolve(response)
	    });
}
  • 由于他们两个的核心逻辑都用 promise 进行封装了,因此我们可以用 promise 的 then 语法来构建 promise 链保证他们可以顺序执行。

    async 执行一天的事情(){A 发送微信消息().then(()=>{B 吃饭的时间()
    		}
    	)
    	洗车();
    	洗碗();
    	洗盘子()
    }
    
  • 这样就能保证 约 B 吃饭的时间() 一定要发生在 A 这个函数完全完成之后;

  • 但同时,其他的程序还是能够正常执行(不阻塞)

  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暖仔会飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值