添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
瘦瘦的烈马  ·  sql进阶 - ...·  1 年前    · 
开心的刺猬  ·  在matplotlib ...·  1 年前    · 
酒量小的椰子  ·  android ...·  1 年前    · 

有个需求,某个异步请求函数可能被多次调用,重复调用消耗资源,需要对其进行优化

  1. 每次调用该函数都能取到返回值
  2. 只发送一次异步请求

这个 和节流、防抖功能不一样 ,节流防抖会丢弃掉中间的请求,中间的请求获取不到返回值,这里要求每一个函数调用都能取到返回值。

很容易想到使用 同步非阻塞 方案,在第一个点击时,进入loading状态,之后的点击判断loading就等50毫秒继续检查loading的值,直到loading为false,返回localEnv。这里使用setTimeout来模拟异步请求。

< input onclick = " clickMe() " type = " button " value = " 点我 " > </ body >
async function clickMe() {
  const env = await getEnv()
  console.log(env)
let localEnv
let loading = false
async function getEnv() {
  if (localEnv) {
    return localEnv
  // 若正在请求中,则每50毫秒检查loading状态,直到为false,返回请求结果
  if (loading) {
    // 同步非阻塞
    while(loading) {
      await wait(50)
    return localEnv
  } else {
    loading = true
    return new Promise((resolve, reject) => {
      console.log('questing env......')
      setTimeout(() => {
        localEnv = {
          platform: '141001',
          appid: 'aoshdakhpa8fkdng'
        loading = false
        resolve(localEnv)
      }, 2000)
function wait (time) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve()
    }, time)

方案一主要由于循环去检测loading的状态,导致不那么高效

Java中可以通过锁机制,使用wait/notify轻易实现该功能。JavaScript也可以利用锁机制来实现类似wait/notify的功能。
JavaScript可以通过resolve/reject函数来实现锁,在没有调用resolve/reject函数时,promise会看起来相当于一直阻塞(其实和Java的阻塞不一样,这里只是没有执行后续的函数)。

<input onclick="clickMe()" type="button" value="点我"> </body>
async function clickMe() {
  const env = await getEnv()
  console.log(env)
let localEnv, p
const queue = []
let loading = false
async function getEnv() {
  return new Promise((resolve, reject) => {
    if (localEnv) {
      resolve(localEnv)
    // 进入这个if的Promise没有调用resolve(),会一直阻塞
    if (loading) {
      // 把resolve存入数组,待请求返回后执行resolve
      queue.push({resolve, reject})
    if (!loading && !localEnv) {
      loading = true
      console.log('questing env......')
      setTimeout(() => {
        localEnv = {
          platform: '141001',
          appid: 'aoshdakhpa8fkdng'
        loading = false
        resolve(localEnv)
        // 异步请求结束,调用所有正在阻塞的Promise的resolve函数,返回结果,解除阻塞
        while (p = queue.shift()) {
          p.resolve(localEnv)
      }, 2000)

利用好Promise没有resolve/reject会一直阻塞的特性,可以实现类似Java的wait/notify功能,实现同一时间多次异步请求函数都取到返回值,只触发一次异步请求的功能。

一次提交,发起多次请求的问题,很可能因为是因为在执行提交的时候,是通过触发一个脚本方法实现的。而脚本方法又是通过JQ来选中表单控件,如果页面中有多个表单,而多个表单控件都被JQ选择器选中,那么就会出现一次提交发起多次请求的问题。 当然了这只是其中一个可能的原因,可以参考一下。 Angular.js的一组异步定模式 此自述文件包含基本用法示例和有关完整API的详细信息,包括方法,属性和帮助程序功能。 要使用库,包括dist/async-lock.js或dist/async-lock.min.js在angular.js后您的index.html文件。 异步定组件: 所有组件都包含在boriskozo.async-locks angular.js模块中。 AsyncLockFactory允许您创建异步。 AsyncLockService环绕AsyncLockFactory环绕以提供对的管理。 为什么在单线程环境中需要异步? 当您JavaScript代码以单线程方式运行时(即,只有一个线程在同一上下文中运行每个函数),而整个代码则在多线程环境中运行。 考虑一个从服务器获一些数据,将其更新并将其保存回服务器的函数。 您的代码如下 在前端页面开发的过程中,经常使用到Ajax请求,异步提交表单数据,或者异步刷新页面。 一般来说,使用Jquery中的$.ajax,$.post,$.getJSON,非常方便,但是有的时候,我们只需要ajax功能,这样引入Jquery比较不划算。 所以接下来便用原生JavaScrpit实现一个简单的Ajax请求,并说明ajax请求中的跨域访问问题,以及多个ajax请求的数据同步问题。 JavaScript实现Ajax异步请求 简单的ajax请求实现 Ajax请求的原理是创建一个XMLHttpRequest对象,使用这个对象来进行异步发送请求,具体实现参考下面代码: function ajax( 问题描述: 最近,在uniapp上实现一个页面功能,需要在onReady之后获canvasContext进行绘制,但是里面用到的一些参数,需要在onLoad上进行传参拿到,由于不同的手机,渲染速度不同,因此导致 onReady 与 onLoad 的执行先后顺序不确定,从而影响到后面的功能操作。 解决方案: 在后端,我们会想到直接使用来解决这个问题。但在JavaScript里面,是没有多线程的,因此也就不存在。在这里,我使用Promise实现。 Lock.js 问题:在弹窗中有个按钮,点击上线,会在列表中添加一条数据,然后弹窗消失。现在在点击按钮时,由于点击过快,在点击上线按钮到弹窗消失期间,导致请求了多次数据,造成了在列表多出了几次同一时间的信息。希望在上线按钮到弹窗消失期间,只请求一次。 解决方法一:使用this.$nextTick(),nextTick(),是将回调函数延迟在下一次dom更新数据后调用,简单的理解是:当数据更新了,在dom中渲染后,自动执行该函数, 在弹窗组件中的data定义一个flag,表示请求状态 data() { 最近项目总结,如果一个输入框和一个搜索按钮,点击查询的时候,需要发起请求数据,因为请求是异步的,则无法获哪一次的请求是最后一次的请求,则可以进行一下操作优化: 思路一:请求外部存在一个变量,记录每次请求的标记;可以将外部的标记传入调用请求的内部,因为函数有作用域的概念,所以暂时目前传入的数据是会一直存在于该作用域内部的,但是外部的标记会一直变化,当是最后一次请求的时候,外部的和内部接收的是相同的,可以在此处进行数据处理。 vue代码如下: <template> 闭包两个特性:1、访问外部函数;2、维持作用域。 维持作用与主要体现在外部函数调用完毕后,其中变量赋内部函数 在调用变量时可访问内部函数及其调用的内部函数访问的外部变量。 代码如下: var global; function out() { var value = 1; function inner() { return value; global = inner; out(); global() // re var that = this; var myClassData = this.data.myData; if (!(myClassData[id] && myClassData[id].length)){//限制只请求一次,当有数据时候就不发起请求了 wx....