Skip to content

Commit 71cefe1

Browse files
author
Raphaël Droz
committed
- Make resume(), pause(), cancel(), removeFile(), and retry() async since these
deal with async operations under the hood. - Remove the need to call readFinished() from the `readFileFn`
1 parent 75d6bd4 commit 71cefe1

File tree

8 files changed

+41
-65
lines changed

8 files changed

+41
-65
lines changed

README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -168,17 +168,17 @@ parameter must be adjusted together with `progressCallbacksInterval` parameter.
168168
* `.off(event)` Remove all callbacks of specific event.
169169
* `.off(event, callback)` Remove specific callback of event. `callback` should be a `Function`.
170170
* `.upload()` [async] Start or resume uploading.
171-
* `.pause()` Pause uploading.
172-
* `.resume()` Resume uploading.
173-
* `.cancel()` Cancel upload of all `FlowFile` objects and remove them from the list.
171+
* `.pause()` [async] Pause uploading.
172+
* `.resume()` [async] Resume uploading.
173+
* `.cancel()` [asyc] Cancel upload of all `FlowFile` objects and remove them from the list.
174174
* `.progress()` Returns a float between 0 and 1 indicating the current upload progress of all files.
175175
* `.isUploading()` Returns a boolean indicating whether or not the instance is currently uploading anything.
176176
* `.addFile(file, event = null, initFileFn = undefined)` [async] Add a HTML5 File object to the list of files.
177177
* Accept the same `event` and `initFileFn` parameters thant `addFiles` which is used under the hood.
178178
* `.addFiles([files], event = null, initFileFn = undefined)` [async] Add multiple File objects to the list of files and returns the promise of the corresponding FlowFiles.
179179
* `event` The optional event that trigger the addition (for internal purposes)
180180
* `initFileFn` An [async] override of Flow.initFileFn
181-
* `.removeFile(file)` Cancel upload of a specific `FlowFile` object on the list from the list.
181+
* `.removeFile(file)` [asyc] Cancel upload of a specific `FlowFile` object on the list from the list.
182182
* `.getFromUniqueIdentifier(uniqueIdentifier)` Look up a `FlowFile` object by its unique identifier.
183183
* `.getSize()` Returns the total size of the upload in bytes.
184184
* `.sizeUploaded()` Returns the total size uploaded of all files in bytes.
@@ -234,7 +234,7 @@ FlowFile constructor can be accessed in `Flow.FlowFile`.
234234
* `.progress(relative)` Returns a float between 0 and 1 indicating the current upload progress of the file. If `relative` is `true`, the value is returned relative to all files in the Flow.js instance.
235235
* `.pause()` Pause uploading the file.
236236
* `.resume()` [async] Resume uploading the file.
237-
* `.cancel()` Abort uploading the file and delete it from the list of files to upload.
237+
* `.cancel()` [async] Abort uploading the file and delete it from the list of files to upload.
238238
* `.retry()` [async] Retry uploading the file.
239239
* `.bootstrap()` [async / internal use only] Rebuild the state of a `FlowFile` object, including reassigning chunks and XMLHttpRequest instances.
240240
* `.isUploading()` Returns a boolean indicating whether file chunks is uploading.

src/Flow.js

+11-18
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import Eventizer from './Eventizer';
66
import FlowFile from './FlowFile';
7-
import {each, webAPIFileRead} from './tools';
7+
import {each} from './tools';
88

99
/**
1010
* Flow.js is a library providing multiple simultaneous, stable and
@@ -33,7 +33,6 @@ import {each, webAPIFileRead} from './tools';
3333
* @param {Array.<number>} [opts.successStatuses]
3434
* @param {Function} [opts.initFileFn]
3535
* @param {Function} [opts.readFileFn]
36-
* @param {Function} [opts.asyncReadFileFn]
3736
* @param {Function} [opts.generateUniqueIdentifier]
3837
* @constructor
3938
*/
@@ -101,8 +100,7 @@ export default class Flow extends Eventizer {
101100
successStatuses: [200, 201, 202],
102101
onDropStopPropagation: false,
103102
initFileFn: null,
104-
readFileFn: webAPIFileRead,
105-
asyncReadFileFn: null
103+
readFileFn: (fileObj, startByte, endByte, fileType, chunk) => fileObj.file.slice(startByte, endByte, fileType)
106104
};
107105

108106
/**
@@ -450,34 +448,29 @@ export default class Flow extends Eventizer {
450448

451449
/**
452450
* Resume uploading.
451+
* @return [<Promise>]
453452
* @function
454453
*/
455454
resume() {
456-
each(this.files, function (file) {
457-
if (!file.isComplete()) {
458-
file.resume();
459-
}
460-
});
455+
return Promise.all(this.files.filter(file => !file.isComplete()).map(file => file.resume()));
461456
}
462457

463458
/**
464459
* Pause uploading.
460+
* @return [<Promise>]
465461
* @function
466462
*/
467463
pause() {
468-
each(this.files, function (file) {
469-
file.pause();
470-
});
464+
return Promise.all(this.files.map(file => file.pause()));
471465
}
472466

473467
/**
474468
* Cancel upload of all FlowFile objects and remove them from the list.
469+
* @return [<Promise>]
475470
* @function
476471
*/
477472
cancel() {
478-
for (var i = this.files.length - 1; i >= 0; i--) {
479-
this.files[i].cancel();
480-
}
473+
return Promise.all(this.files.reverse().map(file => file.cancel()));
481474
}
482475

483476
/**
@@ -568,7 +561,7 @@ export default class Flow extends Eventizer {
568561
flowfiles = flowfiles.filter(e => e && e.file);
569562
for (let file of flowfiles) {
570563
if (this.opts.singleFile && this.files.length > 0) {
571-
this.removeFile(this.files[0]);
564+
await this.removeFile(this.files[0]);
572565
}
573566
this.files.push(file);
574567
}
@@ -582,11 +575,11 @@ export default class Flow extends Eventizer {
582575
* @function
583576
* @param {FlowFile} file
584577
*/
585-
removeFile(file) {
578+
async removeFile(file) {
586579
for (var i = this.files.length - 1; i >= 0; i--) {
587580
if (this.files[i] === file) {
588581
this.files.splice(i, 1);
589-
file.abort();
582+
await file.abort();
590583
this.emit('file-removed', file);
591584

592585
if (!this.opts.allowDuplicateUploads) {

src/FlowChunk.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,8 @@ export default class FlowChunk {
396396
switch (this.readState) {
397397
case 0:
398398
this.readState = 1;
399-
read(this.fileObj, this.startByte, this.endByte, this.fileObj.file.type, this);
399+
const data = read(this.fileObj, this.startByte, this.endByte, this.fileObj.file.type, this);
400+
this.readFinished(data);
400401
return;
401402
case 1:
402403
return;

src/FlowFile.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -173,16 +173,18 @@ export default class FlowFile {
173173

174174
/**
175175
* Pause file upload
176+
* @return Promise
176177
* @function
177178
*/
178179
pause() {
179180
this.paused = true;
180-
this.abort();
181+
return this.abort();
181182
}
182183

183184
/**
184185
* Resume file upload
185186
* @return Promise
187+
* @function
186188
*/
187189
resume() {
188190
this.paused = false;
@@ -193,7 +195,7 @@ export default class FlowFile {
193195
* Abort current upload
194196
* @function
195197
*/
196-
abort(reset) {
198+
async abort(reset) {
197199
this.currentSpeed = 0;
198200
this.averageSpeed = 0;
199201
if (reset) {
@@ -203,26 +205,28 @@ export default class FlowFile {
203205
if (c.status() === 'uploading') {
204206
c.abort();
205207
c.pendingRetry = true;
206-
this.flowObj.uploadNextChunk();
208+
await this.flowObj.uploadNextChunk();
207209
}
208210
}
209211
}
210212

211213
/**
212214
* Cancel current upload and remove from a list
215+
* @return Promise
213216
* @function
214217
*/
215218
cancel() {
216-
this.flowObj.removeFile(this);
219+
return this.flowObj.removeFile(this);
217220
}
218221

219222
/**
220223
* Retry aborted file upload
224+
* @return Promise
221225
* @function
222226
*/
223227
async retry() {
224228
await this.bootstrap('retry');
225-
return await this.flowObj.upload();
229+
return this.flowObj.upload();
226230
}
227231

228232
async bootstrap(event = null, initFileFn = this.flowObj.opts.initFileFn) {

src/tools.js

+1-21
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,3 @@
1-
/**
2-
* Default read function using the webAPI
3-
*
4-
* @function webAPIFileRead(fileObj, startByte, endByte, fileType, chunk)
5-
*
6-
*/
7-
function webAPIFileRead(fileObj, startByte, endByte, fileType, chunk) {
8-
var function_name = 'slice';
9-
10-
if (fileObj.file.slice)
11-
function_name = 'slice';
12-
else if (fileObj.file.mozSlice)
13-
function_name = 'mozSlice';
14-
else if (fileObj.file.webkitSlice)
15-
function_name = 'webkitSlice';
16-
17-
chunk.readFinished(fileObj.file[function_name](startByte, endByte, fileType));
18-
}
19-
201
/**
212
* If option is a function, evaluate it with given params
223
* @param {*} data
@@ -72,6 +53,5 @@ g.evalOpts = evalOpts;
7253

7354
export {
7455
each,
75-
evalOpts,
76-
webAPIFileRead
56+
evalOpts
7757
};

test/asyncSpec.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -170,12 +170,12 @@ describe('upload stream', function() {
170170
expect(customFunction).toHaveBeenCalledTimes(1);
171171

172172
// But if removed, then the function is run again
173-
flow.removeFile(flowfiles[0]);
173+
await flow.removeFile(flowfiles[0]);
174174
flowfiles = await flow.addFiles([sample_file], null, initFileFunction);
175175
expect(customFunction).toHaveBeenCalledTimes(2);
176176

177177
// It should work with addFile() too.
178-
flow.removeFile(flowfiles[0]);
178+
await flow.removeFile(flowfiles[0]);
179179
flowfiles = await flow.addFile(sample_file, null, initFileFunction);
180180
expect(customFunction).toHaveBeenCalledTimes(3);
181181
});
@@ -335,7 +335,7 @@ describe('upload stream', function() {
335335
// Next two chunks from file[0] were read but we abort() their
336336
// corresponding `xhr`. They will get back to pending.
337337
// Flow should start uploading second file now
338-
files[0].pause();
338+
await files[0].pause();
339339
await waitFor(() => xhr_server.requests.length == 6);
340340

341341
/*
@@ -364,7 +364,7 @@ describe('upload stream', function() {
364364
[ooR]
365365
*/
366366
// Should resume file after second file chunks is uploaded
367-
files[0].resume();
367+
await files[0].resume();
368368
await sleep(1);
369369

370370
/*

test/fileRemoveSpec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ describe('file-removed event', function() {
2222
});
2323
await flow.addFile(new Blob(['file part']));
2424
var addedFile = flow.files[0];
25-
flow.removeFile(addedFile);
25+
await flow.removeFile(addedFile);
2626
expect(removedFile).toBe(addedFile);
2727
expect(valid).toBeTruthy();
2828
});
@@ -37,7 +37,7 @@ describe('file-removed event', function() {
3737
});
3838
await flow.addFile(new Blob(['file part']));
3939
var addedFile = flow.files[0];
40-
addedFile.cancel();
40+
await addedFile.cancel();
4141
expect(removedFile).toBe(addedFile);
4242
expect(valid).toBeTruthy();
4343
});

test/uploadSpec.js

+7-9
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ describe('upload file', function() {
139139
expect(xhr.requests[0].aborted).toBeUndefined();
140140
expect(xhr.requests[1].aborted).toBeUndefined();
141141
// should start upload second file
142-
files[0].pause();
142+
await files[0].pause();
143143
expect(files[0].isUploading()).toBeFalsy();
144144
expect(files[1].isUploading()).toBeTruthy();
145145
expect(xhr.requests.length).toBe(4);
@@ -148,7 +148,7 @@ describe('upload file', function() {
148148
expect(xhr.requests[2].aborted).toBeUndefined();
149149
expect(xhr.requests[3].aborted).toBeUndefined();
150150
// Should resume file after second file chunks is uploaded
151-
files[0].resume();
151+
await files[0].resume();
152152
expect(files[0].isUploading()).toBeFalsy();
153153
expect(xhr.requests.length).toBe(4);
154154
xhr.requests[2].respond(200);// second file chunk
@@ -440,8 +440,8 @@ describe('upload file', function() {
440440
for(var i=0; i<file.chunks.length; i++) {
441441
expect(preprocess).toHaveBeenCalledWith(file.chunks[i]);
442442
file.chunks[i].preprocessFinished();
443-
file.pause();
444-
file.resume();
443+
await file.pause();
444+
await file.resume();
445445
xhr.requests[xhr.requests.length-1].respond(200, [], "response");
446446
}
447447
expect(success).toHaveBeenCalledWith(asCustomEvent(file, "response", file.chunks[file.chunks.length-1]));
@@ -515,10 +515,10 @@ describe('upload file', function() {
515515
xhr.requests[2].uploadProgress({loaded: 10, total: 15});
516516
expect(fileThird.timeRemaining()).toBe(1);
517517
expect(flow.timeRemaining()).toBe(1);
518-
fileThird.pause();
518+
await fileThird.pause();
519519
expect(fileThird.timeRemaining()).toBe(0);
520520
expect(flow.timeRemaining()).toBe(0);
521-
fileThird.resume();
521+
await fileThird.resume();
522522
expect(fileThird.timeRemaining()).toBe(Number.POSITIVE_INFINITY);
523523
expect(flow.timeRemaining()).toBe(Number.POSITIVE_INFINITY);
524524
clock.tick(1000);
@@ -558,9 +558,7 @@ describe('upload file', function() {
558558
flowObj.size = flowObj.file.size;
559559
}
560560

561-
flow.opts.readFileFn = function(fileObj, startByte, endByte, fileType, chunk) {
562-
chunk.readFinished('X');
563-
}
561+
flow.opts.readFileFn = (fileObj, startByte, endByte, fileType, chunk) => 'X';
564562

565563
await flow.addFile(new Blob(['0123456789']));
566564

0 commit comments

Comments
 (0)