流浪のwolf

卷帝

导航

异步编程的理解

异步行为是为了优化因计算量大而 时间长的操作

同步:每条指令都会严格按照它们出现的顺序来执行 ;

相对地,异步行为类似于系统中断,即当前进程外部的实体可以触发代码执行 ; 

异步编程是必要的:如果代码要访问 一些高延迟的资源,比如向远程服务器发送请求并等待响应,那么就会出现长时间的等待

1. 以往的异步编程模式

异步行为是 JavaScript 的基础,但以前的实现不理想。在早期的 JavaScript 中,只支持定义回调函数 来表明异步操作完成。串联多个异步操作是一个常见的问题,通常需要深度嵌套的回调函数(俗称“回 调地狱”)来解决; 

function double(value, success, failure) {
 setTimeout(() => {
 try {
 if (typeof value !== 'number') {
 throw 'Must provide number as first argument';
 }
 success(2 * value);
 } catch (e) {
 failure(e);
 }
 }, 1000);
}
const successCallback = (x) => {
 double(x, (y) => console.log(`Success: ${y}`));
};
const failureCallback = (e) => console.log(`Failure: ${e}`);
double(3, successCallback, failureCallback);
// Success: 12(大约 1000 毫秒之后)

随着代码越来越复杂,回调策略是不具有扩展性的。“回调地狱”这个称呼可谓名至实归。 嵌套回调的代码维护起来就是噩梦。

2. promise 期约

期约是对尚不存在结果的一个替身。

ECMAScript 6 新增的引用类型 Promise,可以通过 new 操作符来实例化。创建新期约时需要传入 执行器(executor)函数作为参数(要执行的任务);

Promise的三种状态:待定(pending)

pending、fulfilled、rejected(未决定,履行,拒绝),同一时间只能存在一种状态,且状态一旦改变就不能再变。promise是一个构造函数,promise对象代表一项有两种可能结果(成功或失败)的任务,它还持有多个回调,出现不同结果时分别发出相应回调。

1.初始化,状态:pending

let p = new Promise(() => {});
        setTimeout(console.log, 0, p); // Promise <pending>

2.当调用resolve(成功),状态:pengding=>fulfilled

3.当调用reject(失败),状态:pending=>rejected

期约故意将异步行为封装起来,从而隔离外部的同步代码。

期约主要有两大用途。首先是抽象地表示一个异步操作。期约的状态代表期约是否完成。“待定” 表示尚未开始或者正在执行中。“兑现”表示已经成功完成,而“拒绝”则表示没有成功完成。

期约的状态只能改变一次,

3. 期约的thenable接口

Promise.prototype.then()是为期约实例添加处理程序的主要方法。这个 then()方法接收最多 两个参数:onResolved 处理程序和 onRejected 处理程序。这两个参数都是可选的,如果提供的话, 则会在期约分别进入“兑现”和“拒绝”状态时执行 ; 

onRejected 处理程序的任务不就是捕获异步错误吗? 因此,拒绝处理程序在捕获错误后不抛出异常是符合期约的行为,

4. catch接口

Promise.prototype.catch()方法用于给期约添加拒绝处理程序。这个方法只接收一个参数: onRejected 处理程序。事实上,这个方法就是一个语法糖,调用它就相当于调用 Promise.prototype. then(null, onRejected)。

在返回新期约实例方面,Promise.prototype.catch()的行为与 Promise.prototype.then() 的 onRejected 处理程序是一样的。

 

posted on 2022-09-09 09:00  流浪のwolf  阅读(56)  评论(0编辑  收藏  举报