4

ES6异步处理解决方案

 1 year ago
source link: https://www.fly63.com/article/detial/11643
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

更新日期: 2022-06-02阅读量: 28标签: 异步分享

扫一扫分享

以下文章来源于javascript艺术 ,作者zhangjing

ES6的异步处理模型分为俩个阶段三种状态。

  • 两个阶段:未决unsettled, 已决settled。
  • 三个状态:pending挂起状态 , resolved成功, rejected失败
6298711a605a5.jpg

通常把从未决推向已决的resolved状态的过程叫做resolve,从未决推向已决的rejected状态的过程,叫做reject

6298711eed05f.jpg

任务已决状态后可能需要后续处理,若任务成功了(resolved),有后续处理,如果任务失败了(rejected),仍然有后续处理,把针对resolved的后续处理,称为thenable,针对rejected的后续处理,称为catchable;

  • 针对resolved的后续处理我们称之为thenable
  • 针对rejected的后续处理我们称之为catchable
62987123937ff.jpg

Promise 对象

什么是Promise

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 api,各种异步操作都可以用同样的方法进行处理。

Promise对象有以下两个特点。

1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和Rejected(已失败)。

2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。

有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。

Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

Promise用法

ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。

const task = new Promise((resolve, reject) => {     
// 任务未决阶段代码
// 立即执行
console.log("开始");
setTimeout(() => {
if (Math.random() > 0.5) {
// 成功
// 推向成功
resolve("成功");
} else {
// 失败
// 推向失败
reject("失败");
}
}, 1000)
});
task.then((result) => {
console.log(result);
}).catch((error) => {
console.log(error);
})

resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

Promise.prototype.then()

then方法是定义在原型对象Promise.prototype上的。then方法的第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数。then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。

getJSON("/posts.json").then(function(json) {
return json.post;
}).then(function(post) {
// ...
});

采用链式的then,可以指定一组按照次序调用的回调函数。这时,前一个回调函数,有可能返回的还是一个Promise对象(即有异步操作),这时后一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用。

Promise.prototype.catch()

如果异步操作抛出错误,状态就会变为rejected,就会调用catch()方法指定的回调函数,处理这个错误。另外,then()方法指定的回调函数,如果运行中抛出错误,也会被catch()方法捕获。

catch方法返回的还是一个 Promise 对象。

getJSON('/posts.json').then(function(posts) {
// ...
}).catch(function(error) {
// 处理 getJSON 和 前一个回调函数运行时发生的错误
console.log('发生错误!', error);
});
Promise.prototype.finally()

finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
Promise.prototype.all()

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.all([p1, p2, p3]);

p的状态由p1、p2、p3决定,分成两种情况。

(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。

(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

Promise.race()

Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.race([p1, p2, p3]);

只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

async/await

async函数在function前面有个async作为标识,意思就是异步函数,里面有个await搭配使用,每到await的地方就是程序需要等待执行后面的程序,语义化很强。

  • await只能在async函数中使用

  • await后面的语句可以是promise对象、数字、字符串等

  • async函数返回的是一个Promsie对象

  • await语句后的Promise对象变成reject状态时,那么整个async函数会中断,后面的程序不会继续执行

  • async中如果没有return,返回值是Promise,但是没有值;async中如果有return,return的值会作为返回Promise的then的值

async function getStockPriceByName(name) {
const symbol = await getStockSymbol(name);
const stockPrice = await getStockPrice(symbol);
return stockPrice;
}

getStockPriceByName('goog').then(function (result) {
console.log(result);
});

try/catch/finally 语句用于处理代码中可能出现的错误信息。

  • try语句允许我们定义在执行时进行错误测试的代码块。

  • catch 语句允许我们定义当 try 代码块发生错误时,所执行的代码块。

  • finally 语句在 try 和 catch 之后无论有无异常都会执行。

注意 :catch 和 finally 语句都是可选的,但你在使用 try 语句时必须至少使用一个。

提示 :当错误发生时, JavaScript 会停止执行,并生成一个错误信息。使用 throw 语句 来创建自定义消息(抛出异常)。如果你将 throw 和 try 、 catch一起使用,就可以控制程序输出的错误信息。

async function main() {
try {
const val1 = await firstStep();
const val2 = await secondStep(val1);
const val3 = await thirdStep(val1, val2);

console.log('Final: ', val3);
}
catch (err) {
console.error(err);
}
}

链接: https://www.fly63.com/article/detial/11643


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK