前端异步解决方案大全(2021版)(二)

简介: 前端异步解决方案大全(2021版)

二、工具方案

工具方案大致分为以下5个:

  • Promise
  • gengerator函数
  • async await
  • node.js中 nextTick setImmidate
  • 第三方库 async.js

下面针对每一个做详细说明应用:

1、Promise(重点)

Promise的含义和发展


含义:Promise 对象用于一个异步操作的最终完成(或失败)及其结果值的表示。简单点说,它就是用于处理异步操作的,异步处理成功了就执行成功的操作,异步处理失败了就捕获错误或者停止后续操作。


发展:Promise 是异步编程的一种解决方案,比传统的解决方案(回调函数和事件监听)更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了语法,原生提供了Promise。


它的一般形式:


new Promise(
    /* executor */
    function(resolve, reject) {
        if (/* success */) {
            // ...执行代码
            resolve();
        } else { /* fail */
            // ...执行代码
            reject();
        }
    }
);

其中,Promise中的参数executor是一个执行器函数,它有两个参数resolve和reject。它内部通常有一些异步操作,如果异步操作成功,则可以调用resolve()来将该实例的状态置为fulfilled,即已完成的,如果一旦失败,可以调用reject()来将该实例的状态置为rejected,即失败的。


我们可以把Promise对象看成是一条工厂的流水线,对于流水线来说,从它的工作职能上看,它只有三种状态,一个是初始状态(刚开机的时候),一个是加工产品成功,一个是加工产品失败(出现了某些故障)。同样对于Promise对象来说,它也有三种状态:pending: 初始状态,也称为未定状态,就是初始化Promise时,调用executor执行器函数后的状态。 fulfilled:完成状态,意味着异步操作成功。


pending:初始状态,也称为未定状态,就是初始化Promise时,调用executor执行器函数后的状态。

fulfilled:完成状态,意味着异步操作成功。

rejected:失败状态,意味着异步操作失败。

它只有两种状态可以转化,即:


操作成功:pending -> fulfilled

操作失败:pending -> rejected

注意:并且这个状态转化是单向的,不可逆转,已经确定的状态(fulfilled/rejected)无法转回初始状态(pending)。


Promise对象的方法(api)

(1).Promise.prototype.then(callback)


Promise对象含有then方法,then()调用后返回一个Promise对象,意味着实例化后的Promise对象可以进行链式调用,而且这个then()方法可以接收两个函数,一个是处理成功后的函数,一个是处理错误结果的函数。

如下:

var promise1 = new Promise(function(resolve, reject) {
  // 2秒后置为接收状态
  setTimeout(function() {
    resolve('success');
  }, 2000);
});
promise1.then(function(data) {
  console.log(data); // success
}, function(err) {
  console.log(err); // 不执行
}).then(function(data) {
  // 上一步的then()方法没有返回值
  console.log('链式调用:' + data); // 链式调用:undefined 
}).then(function(data) {
  // ....
});

在这里我们主要关注promise1.then()方法调用后返回的Promise对象的状态,是pending还是fulfilled,或者是rejected?


返回的这个Promise对象的状态主要是根据promise1.then()方法返回的值,大致分为以下几种情况:


如果then()方法中返回了一个参数值,那么返回的Promise将会变成接收状态。

如果then()方法中抛出了一个异常,那么返回的Promise将会变成拒绝状态。

如果then()方法调用resolve()方法,那么返回的Promise将会变成接收状态。

如果then()方法调用reject()方法,那么返回的Promise将会变成拒绝状态。

如果then()方法返回了一个未知状态(pending)的Promise新实例,那么返回的新Promise就是未知 状态。

如果then()方法没有明确指定的resolve(data)/reject(data)/return data时,那么返回的新Promise就是接收状态,可以一层一层地往下传递。

(2).Promise.prototype.catch(callback)


catch()方法和then()方法一样,都会返回一个新的Promise对象,它主要用于捕获异步操作时出现的异常。因此,我们通常省略then()方法的第二个参数,把错误处理控制权转交给其后面的catch()函数,如下:

var promise3 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    reject('reject');
  }, 2000);
});
promise3.then(function(data) {
  console.log('这里是fulfilled状态'); // 这里不会触发
  // ...
}).catch(function(err) {
  // 最后的catch()方法可以捕获在这一条Promise链上的异常
  console.log('出错:' + err); // 出错:reject
});

(3).Promise.all()


Promise.all()接收一个参数,它必须是可以迭代的,比如数组。


它通常用来处理一些并发的异步操作,即它们的结果互不干扰,但是又需要异步执行。它最终只有两种状态:成功或者失败。


指的是将数组中所有的任务执行完成之后, 才执行.then 中的任务


它的状态受参数内各个值的状态影响,即里面状态全部为fulfilled时,它才会变成fulfilled,否则变成rejected。


成功调用后返回一个数组,数组的值是有序的,即按照传入参数的数组的值操作后返回的结果。


如下:

const p1 = new Promise((resolve,reject)=>{
  setTimeout(()=>{
    resolve(console.log('p1 任务1'))
  },1000)
})
  .then( data => {
    console.log('p1 任务2')
  })
  .then( res => {
    console.log('p1 任务3')
  })
  .catch( err =>{ throw err} )
const p2 = new Promise((resolve,reject)=>{
  resolve(console.log('p2 任务1'))
}).then(
  data => {
    console.log('p2 任务2')
  }
).catch(
  err => {
    throw err 
  }
)
//只有在p1,p2都执行完后才会执行then里的内容
Promise.all([p1,p2])
 .then(()=>console.log('done'))

(4).Promise.race()


Promise.race()和Promise.all()类似,都接收一个可以迭代的参数,但是不同之处是Promise.race()的状态变化不是全部受参数内的状态影响,一旦参数内有一个值的状态发生的改变,那么该Promise的状态就是改变的状态。就跟race单词的字面意思一样,谁跑的快谁赢。如下:


var p1 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 300, 'p1 doned');
});
var p2 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 50, 'p2 doned');
});
var p3 = new Promise(function(resolve, reject) {
  setTimeout(reject, 100, 'p3 rejected');
});
Promise.race([p1, p2, p3]).then(function(data) {
  // 显然p2更快,所以状态变成了fulfilled
  // 如果p3更快,那么状态就会变成rejected
  console.log(data); // p2 doned
}).catch(function(err) {
  console.log(err); // 不执行
});

(5).Promise.resolve()


Promise.resolve()接受一个参数值,可以是普通的值,具有then()方法的对象和Promise实例。正常情况下,它返回一个Promise对象,状态为fulfilled。但是,当解析时发生错误时,返回的Promise对象将会置为rejected态。如下:

// 参数为普通值
var p4 = Promise.resolve(5);
p4.then(function(data) {
  console.log(data); // 5
});
// 参数为含有then()方法的对象
var obj = {
  then: function() {
    console.log('obj 里面的then()方法');
  }
};
var p5 = Promise.resolve(obj);
p5.then(function(data) {
  // 这里的值时obj方法里面返回的值
  console.log(data); // obj 里面的then()方法
});
// 参数为Promise实例
var p6 = Promise.resolve(7);
var p7 = Promise.resolve(p6);
p7.then(function(data) {
  // 这里的值时Promise实例返回的值
  console.log(data); // 7
});
// 参数为Promise实例,但参数是rejected态
var p8 = Promise.reject(8);
var p9 = Promise.resolve(p8);
p9.then(function(data) {
  // 这里的值时Promise实例返回的值
  console.log('fulfilled:'+ data); // 不执行
}).catch(function(err) {
  console.log('rejected:' + err); // rejected: 8
});

(6).Promise.reject()

Promise.reject()和Promise.resolve()正好相反,它接收一个参数值reason,即发生异常的原因。此时返回的Promise对象将会置为rejected态。如下:

var p10 = Promise.reject('手动拒绝');
p10.then(function(data) {
  console.log(data); // 这里不会执行,因为是rejected态
}).catch(function(err) {
  console.log(err); // 手动拒绝
}).then(function(data) {
 // 不受上一级影响
  console.log('状态:fulfilled'); // 状态:fulfilled
});

总之,除非Promise.then()方法内部抛出异常或者是明确置为rejected态,否则它返回的Promise的状态都是fulfilled态,即完成态,并且它的状态不受它的上一级的状态的影响。

相关文章
|
20天前
|
前端开发 JavaScript API
前端:事件循环/异步
前端开发中的事件循环和异步处理是核心机制,用于管理任务执行、性能优化及响应用户操作,确保网页流畅运行。事件循环负责调度任务,而异步则通过回调、Promise等实现非阻塞操作。
|
2月前
|
前端开发 JavaScript
乾坤qiankun(微前端)样式隔离解决方案--使用插件替换前缀
乾坤qiankun(微前端)样式隔离解决方案--使用插件替换前缀
453 8
|
2月前
|
设计模式 前端开发 JavaScript
前端编程的异步解决方案有哪些?
本文首发于微信公众号“前端徐徐”,介绍了异步编程的背景和几种常见方案,包括回调、事件监听、发布订阅、Promise、Generator、async/await和响应式编程。每种方案都有详细的例子和优缺点分析,帮助开发者根据具体需求选择最合适的异步编程方式。
88 1
|
7月前
|
缓存 监控 前端开发
前端性能优化以及解决方案
前端性能优化关乎用户体验和网站竞争力,包括减少HTTP请求、使用CDN、压缩资源、延迟加载、利用浏览器缓存等策略。制定优化计划,使用监控工具,遵循最佳实践并持续学习,能提升网站速度和稳定性。
88 0
|
4月前
|
开发者 安全 UED
JSF事件监听器:解锁动态界面的秘密武器,你真的知道如何驾驭它吗?
【8月更文挑战第31天】在构建动态用户界面时,事件监听器是实现组件间通信和响应用户操作的关键机制。JavaServer Faces (JSF) 提供了完整的事件模型,通过自定义事件监听器扩展组件行为。本文详细介绍如何在 JSF 应用中创建和使用事件监听器,提升应用的交互性和响应能力。
40 0
|
4月前
|
前端开发 JavaScript 中间件
【前端状态管理之道】React Context与Redux大对决:从原理到实践全面解析状态管理框架的选择与比较,帮你找到最适合的解决方案!
【8月更文挑战第31天】本文通过电子商务网站的具体案例,详细比较了React Context与Redux两种状态管理方案的优缺点。React Context作为轻量级API,适合小规模应用和少量状态共享,实现简单快捷。Redux则适用于大型复杂应用,具备严格的状态管理规则和丰富的社区支持,但配置较为繁琐。文章提供了两种方案的具体实现代码,并从适用场景、维护成本及社区支持三方面进行对比分析,帮助开发者根据项目需求选择最佳方案。
72 0
|
4月前
|
前端开发 测试技术 API
现代前端开发中的跨平台挑战与解决方案探讨
随着移动设备和桌面端用户体验的日益融合,现代前端开发面临着跨平台兼容性的重大挑战。本文将探讨这些挑战的根源,并介绍一些创新的解决方案,帮助开发人员更好地应对不同平台之间的差异,提升应用程序的用户体验和性能。
|
6月前
|
开发框架 前端开发 JavaScript
现代前端开发中的跨平台解决方案比较与应用
在现代软件开发中,跨平台解决方案成为了开发者们的热门话题。本文将探讨几种主流的跨平台开发框架及其特点,重点比较它们在前端开发中的应用场景和优劣势。通过对比分析,读者可以更好地理解如何选择适合自己项目需求的跨平台解决方案。
|
6月前
|
前端开发
前端React篇之React setState 调用的原理、React setState 调用之后发生了什么?是同步还是异步?
前端React篇之React setState 调用的原理、React setState 调用之后发生了什么?是同步还是异步?
|
5月前
|
前端开发
纯前端模拟后端接口异步获取数据
纯前端模拟后端接口异步获取数据
45 0