Sfoglia il codice sorgente

Handle sync returns and throws in possibly-async function options

Fixes #315

This patch makes some function options that can return Promises a bit
easier to use. Previously, most of these required that the user returned
a Promise, even if they were doing sync work. Also, if an error was
thrown inside the provided function, it would actually throw the error
instead of rejecting a Promise, thus not allowing Uppy to show an error
notification or anything.

Instead, these options now use this pattern:

```js
Promise.resolve()
  .then(() => this.opts.onSomething(argument))
```

Inside a `.then()` handler, both a Promise and a plain value can be
returned, and the resulting Promise will be resolved with the correct
value. Also, any sync errors `throw`n inside a `.then()` handler cause
the returned Promise to be rejected.
Renée Kooi 7 anni fa
parent
commit
850c2bb526
3 ha cambiato i file con 15 aggiunte e 4 eliminazioni
  1. 10 2
      src/core/Core.js
  2. 3 1
      src/plugins/AwsS3/index.js
  3. 2 1
      src/plugins/Transloadit/index.js

+ 10 - 2
src/core/Core.js

@@ -263,7 +263,12 @@ class Uppy {
   }
   }
 
 
   addFile (file) {
   addFile (file) {
-    return this.opts.onBeforeFileAdded(file, this.getState().files).catch((err) => {
+    // Wrap this in a Promise `.then()` handler so errors will reject the Promise
+    // instead of throwing.
+    const beforeFileAdded = Promise.resolve()
+      .then(() => this.opts.onBeforeFileAdded(file, this.getState().files))
+
+    return beforeFileAdded.catch((err) => {
       this.info(err, 'error', 5000)
       this.info(err, 'error', 5000)
       return Promise.reject(`onBeforeFileAdded: ${err}`)
       return Promise.reject(`onBeforeFileAdded: ${err}`)
     }).then(() => {
     }).then(() => {
@@ -923,7 +928,10 @@ class Uppy {
       return Promise.reject('Minimum number of files has not been reached')
       return Promise.reject('Minimum number of files has not been reached')
     }
     }
 
 
-    return this.opts.onBeforeUpload(this.state.files).catch((err) => {
+    const beforeUpload = Promise.resolve()
+      .then(() => this.opts.onBeforeUpload(this.state.files))
+
+    return beforeUpload.catch((err) => {
       this.info(err, 'error', 5000)
       this.info(err, 'error', 5000)
       return Promise.reject(`onBeforeUpload: ${err}`)
       return Promise.reject(`onBeforeUpload: ${err}`)
     }).then(() => {
     }).then(() => {

+ 3 - 1
src/plugins/AwsS3/index.js

@@ -81,7 +81,9 @@ module.exports = class AwsS3 extends Plugin {
     return Promise.all(
     return Promise.all(
       fileIDs.map((id) => {
       fileIDs.map((id) => {
         const file = this.core.getFile(id)
         const file = this.core.getFile(id)
-        return this.opts.getUploadParameters(file).then((params) => {
+        const paramsPromise = Promise.resolve()
+          .then(() => this.opts.getUploadParameters(file))
+        return paramsPromise.then((params) => {
           this.core.emit('core:preprocess-progress', file.id, {
           this.core.emit('core:preprocess-progress', file.id, {
             mode: 'determinate',
             mode: 'determinate',
             message: this.locale.strings.preparingUpload,
             message: this.locale.strings.preparingUpload,

+ 2 - 1
src/plugins/Transloadit/index.js

@@ -82,7 +82,8 @@ module.exports = class Transloadit extends Plugin {
     return Promise.all(
     return Promise.all(
       fileIDs.map((fileID) => {
       fileIDs.map((fileID) => {
         const file = this.core.getFile(fileID)
         const file = this.core.getFile(fileID)
-        const promise = Promise.resolve(options.getAssemblyOptions(file, options))
+        const promise = Promise.resolve()
+          .then(() => options.getAssemblyOptions(file, options))
         return promise.then((assemblyOptions) => {
         return promise.then((assemblyOptions) => {
           this.validateParams(assemblyOptions.params)
           this.validateParams(assemblyOptions.params)