Skip to content

Latest commit

 

History

History
263 lines (232 loc) · 5.47 KB

no-restricted-vue-unhandled-promises.md

File metadata and controls

263 lines (232 loc) · 5.47 KB

Enforce Promises in Vue functions with specified syntax to be handled appropriately (no-restricted-vue-unhandled-promises)

We can use asynchronous functions in many scenarios in Vue, but these asynchronous functions tend to generate floating promises, such as lifecycles, watchers, etc.

As a complement to no-restricted-floating-promises, this rule checks for floating promises caused by using await expressions in specific Vue functions.

Options

This rule has a list of string or object options. Each option can be:

  • An AST Selector string
  • An object with the following properties:
    • type: Predefined selector, such as vuex-action, element-message-box or vant-dialog
    • selector: An AST Selector string
    • paths: An array of ignore pattern, meaning that promises generated by functions imported from specified modules will be checked
    • message: Custom reporting message

Fail

/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
export default {
  async created() {
    await foo()
  },
}
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
export default {
  created() {
    return foo()
  },
}
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
export default {
  watch: {
    async bar() {
      await foo()
    },
  },
}
<template>
  <span @click="bar"></span>
</template>

<script>
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
export default {
  methods: {
    async bar() {
      await foo()
    },
  },
}
</script>
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
export default {
  setup() {
    onMounted(async () => {
      await foo()
    })
  },
}
<script setup>
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
watch(() => props.bar, async () => {
  await foo()
})
</script>
<script setup>
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
async function bar() {
  await foo()
}
</script>

<template>
  <span @click="bar"></span>
</template>
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
export default {
  async created() {
    await this.bar()
  },
  methods: {
    async bar() {
      await foo()
    },
  }
}
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
export default {
  created() {
    this.bar()
  },
  methods: {
    async bar() {
      await foo()
    },
  }
}
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", { "type": "vuex-action" }] */
export default {
  async created() {
    await this.$store.dispatch('submit')
  },
}
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", { "type": "vuex-action" }] */
export default {
  created() {
    this.submit()
  },
  methods: {
    ...mapActions(['submit']),
  },
}
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", { "type": "element-message-box" }] */
export default {
  async created() {
    await this.$confirm({})
  },
}
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", { "type": "vant-dialog" }] */
export default {
  async created() {
    await this.$dialog.confirm({})
  },
}
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", { "paths": ["foo"] }] */
import { foo } from 'foo'
export default {
  async created() {
    await foo()
  },
}
<script setup>
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
onMounted(async () => {
  await bar()
})
async function bar() {
  await foo()
}
</script>
<script setup>
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
onMounted(() => {
  bar()
})
async function bar() {
  await foo()
}
</script>

Pass

/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
export default {
  async created() {
    await bar()
  },
}
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
export default {
  created() {
    return bar()
  },
}
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
export default {
  async created() {
    try {
      await foo()
    } catch {}
  },
}
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
export default {
  async created() {
    try {
      await Promise.all([
        foo(),
      ])
    } catch {}
  },
}
<script setup>
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", "CallExpression[callee.name='foo']"] */
watchEffect(async () => {
  try {
    await foo()
  } catch {}
})
</script>
/* eslint galaxy/no-restricted-vue-unhandled-promises: ["error", { "paths": ["foo"] }] */
import { foo } from 'bar'
export default {
  async created() {
    await foo()
  },
}