Browse Source

Add ios task cancel implementation, add test case for task cancel #39

Ben Hsieh 8 years ago
parent
commit
05ade3a0d8

+ 1
- 0
src/index.js View File

160
     return promise
160
     return promise
161
   }
161
   }
162
   promise.cancel = (fn) => {
162
   promise.cancel = (fn) => {
163
+    fn = fn || function(){}
163
     RNFetchBlob.cancelRequest(taskId, fn)
164
     RNFetchBlob.cancelRequest(taskId, fn)
164
   }
165
   }
165
 
166
 

+ 6
- 0
src/ios/RNFetchBlob/RNFetchBlob.m View File

347
                ]);
347
                ]);
348
 }
348
 }
349
 
349
 
350
+RCT_EXPORT_METHOD(cancelRequest:(NSString *)taskId callback:(RCTResponseSenderBlock)callback) {
351
+    [RNFetchBlobNetwork cancelRequest:taskId];
352
+    callback(@[[NSNull null], taskId]);
353
+    
354
+}
355
+
350
 #pragma mark RNFetchBlob private methods
356
 #pragma mark RNFetchBlob private methods
351
 
357
 
352
 
358
 

+ 1
- 0
src/ios/RNFetchBlobNetwork.h View File

35
 - (void) sendRequest;
35
 - (void) sendRequest;
36
 
36
 
37
 + (NSMutableDictionary  * _Nullable ) normalizeHeaders:(NSDictionary * _Nullable)headers;
37
 + (NSMutableDictionary  * _Nullable ) normalizeHeaders:(NSDictionary * _Nullable)headers;
38
++ (void) cancelRequest:(NSString *)taskId;
38
 - (void) sendRequest:(NSDictionary  * _Nullable )options contentLength:(long)contentLength bridge:(RCTBridge * _Nullable)bridgeRef taskId:(NSString * _Nullable)taskId withRequest:(NSURLRequest * _Nullable)req callback:(_Nullable RCTResponseSenderBlock) callback;
39
 - (void) sendRequest:(NSDictionary  * _Nullable )options contentLength:(long)contentLength bridge:(RCTBridge * _Nullable)bridgeRef taskId:(NSString * _Nullable)taskId withRequest:(NSURLRequest * _Nullable)req callback:(_Nullable RCTResponseSenderBlock) callback;
39
 
40
 
40
 
41
 

+ 14
- 2
src/ios/RNFetchBlobNetwork.m View File

21
 //
21
 //
22
 ////////////////////////////////////////
22
 ////////////////////////////////////////
23
 
23
 
24
+NSMutableDictionary * taskTable;
25
+
24
 @interface RNFetchBlobNetwork ()
26
 @interface RNFetchBlobNetwork ()
25
 {
27
 {
26
     BOOL * respFile;
28
     BOOL * respFile;
53
     if(taskQueue == nil) {
55
     if(taskQueue == nil) {
54
         taskQueue = [[NSOperationQueue alloc] init];
56
         taskQueue = [[NSOperationQueue alloc] init];
55
     }
57
     }
58
+    if(taskTable == nil) {
59
+        taskTable = [[NSMutableDictionary alloc] init];
60
+    }
56
     return self;
61
     return self;
57
 }
62
 }
58
 
63
 
109
         respFile = NO;
114
         respFile = NO;
110
     }
115
     }
111
     NSURLSessionDataTask * task = [session dataTaskWithRequest:req];
116
     NSURLSessionDataTask * task = [session dataTaskWithRequest:req];
112
-    
117
+    [taskTable setValue:task forKey:taskId];
113
     [task resume];
118
     [task resume];
114
     
119
     
115
     // network status indicator
120
     // network status indicator
189
 - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesWritten totalBytesExpectedToSend:(int64_t)totalBytesExpectedToWrite
194
 - (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesWritten totalBytesExpectedToSend:(int64_t)totalBytesExpectedToWrite
190
 {
195
 {
191
     [self.bridge.eventDispatcher
196
     [self.bridge.eventDispatcher
192
-     sendDeviceEventWithName:@"RNFetchBlobProgress"
197
+     sendDeviceEventWithName:@"RNFetchBlobProgress-upload"
193
      body:@{
198
      body:@{
194
             @"taskId": taskId,
199
             @"taskId": taskId,
195
             @"written": [NSString stringWithFormat:@"%d", totalBytesWritten],
200
             @"written": [NSString stringWithFormat:@"%d", totalBytesWritten],
198
      ];
203
      ];
199
 }
204
 }
200
 
205
 
206
++ (void) cancelRequest:(NSString *)taskId
207
+{
208
+    NSURLSessionDataTask * task = (NSURLSessionDataTask *)[taskTable objectForKey:taskId];
209
+    if(task != nil && task.state == NSURLSessionTaskStateRunning)
210
+        [task cancel];
211
+}
212
+
201
 //- (void) application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {
213
 //- (void) application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {
202
 //    
214
 //    
203
 //}
215
 //}

+ 85
- 28
test/test-0.7.0.js View File

26
 const  dirs = RNFetchBlob.fs.dirs
26
 const  dirs = RNFetchBlob.fs.dirs
27
 
27
 
28
 let prefix = ((Platform.OS === 'android') ? 'file://' : '')
28
 let prefix = ((Platform.OS === 'android') ? 'file://' : '')
29
+let bigfile = null
29
 
30
 
30
 describe('Upload and download large file', (report, done) => {
31
 describe('Upload and download large file', (report, done) => {
31
-  let filename = '22mb-dummy-' + Date.now()
32
+  let filename = Platform.OS+'-0.7.0-22mb-dummy-' + Date.now()
32
   let begin = -1
33
   let begin = -1
33
   let begin2 = -1
34
   let begin2 = -1
34
   let deb = Date.now()
35
   let deb = Date.now()
49
     </Info>)
50
     </Info>)
50
   })
51
   })
51
   .then((res) => {
52
   .then((res) => {
52
-    try {
53
+    bigfile = res.path()
54
+    done()
55
+  })
56
+  // .then((res) => {
57
+  //   bigfile = res.path()
58
+  //   try {
59
+  //   deb = Date.now()
60
+  //   let promise =  RNFetchBlob.fetch('POST', 'https://content.dropboxapi.com/2/files/upload', {
61
+  //     Authorization : `Bearer ${DROPBOX_TOKEN}`,
62
+  //     'Dropbox-API-Arg': '{\"path\": \"/rn-upload/'+filename+'\",\"mode\": \"add\",\"autorename\": true,\"mute\": false}',
63
+  //     'Content-Type' : 'application/octet-stream',
64
+  //   }, RNFetchBlob.wrap(res.path()))
65
+  //   promise.uploadProgress((now, total) => {
66
+  //     if(Date.now() - deb < 1000)
67
+  //       return
68
+  //     deb = Date.now()
69
+  //     if(begin2 === -1)
70
+  //       begin2 = Date.now()
71
+  //     let speed = Math.floor(now / (Date.now() - begin2))
72
+  //     report(<Info uid="100"  key="progress">
73
+  //       <Text>
74
+  //         {`upload ${now} / ${total} bytes (${speed} kb/s)`}
75
+  //         {` ${Math.floor((total-now)/speed/1000)} seconds left`}
76
+  //       </Text>
77
+  //     </Info>)
78
+  //   })
79
+  //   return promise
80
+  // } catch(err) { console.log(err) }
81
+  // })
82
+  // .then((res) => {
83
+  //   report(<Assert
84
+  //     key="upload should success without crashing app"
85
+  //     expect={filename}
86
+  //     actual={res.json().name}/>)
87
+  //   done()
88
+  // })
89
+})
90
+
91
+describe('cancel task should work properly', (report, done) => {
92
+  let filename = Platform.OS+'-0.7.0-cancel-test-22mb-dummy-' + Date.now()
93
+  let bytesWitten = 0
94
+  let deb = Date.now()
95
+  let begin = -1
96
+  let promise =  RNFetchBlob.fetch('POST', 'https://content.dropboxapi.com/2/files/upload', {
97
+    Authorization : `Bearer ${DROPBOX_TOKEN}`,
98
+    'Dropbox-API-Arg': '{\"path\": \"/rn-upload/'+filename+'\",\"mode\": \"add\",\"autorename\": true,\"mute\": false}',
99
+    'Content-Type' : 'application/octet-stream',
100
+  }, RNFetchBlob.wrap(bigfile))
101
+  promise.uploadProgress((now, total) => {
102
+    bytesWitten = now
103
+    if(Date.now() - deb < 1000)
104
+      return
53
     deb = Date.now()
105
     deb = Date.now()
54
-    let promise =  RNFetchBlob.fetch('POST', 'https://content.dropboxapi.com/2/files/upload', {
55
-      Authorization : `Bearer ${DROPBOX_TOKEN}`,
56
-      'Dropbox-API-Arg': '{\"path\": \"/rn-upload/'+filename+'\",\"mode\": \"add\",\"autorename\": true,\"mute\": false}',
57
-      'Content-Type' : 'application/octet-stream',
58
-    }, RNFetchBlob.wrap(res.path()))
59
-    promise.uploadProgress((now, total) => {
60
-      if(Date.now() - deb < 1000)
61
-        return
62
-      deb = Date.now()
63
-      if(begin2 === -1)
64
-        begin2 = Date.now()
65
-      let speed = Math.floor(now / (Date.now() - begin2))
66
-      report(<Info uid="100"  key="progress">
67
-        <Text>
68
-          {`upload ${now} / ${total} bytes (${speed} kb/s)`}
69
-          {` ${Math.floor((total-now)/speed/1000)} seconds left`}
70
-        </Text>
71
-      </Info>)
72
-    })
73
-    return promise
74
-  } catch(err) { console.log(err) }
106
+    if(begin === -1)
107
+      begin = Date.now()
108
+    let speed = Math.floor(now / (Date.now() - begin))
109
+    report(<Info uid="100"  key="progress">
110
+      <Text>
111
+        {`upload ${now} / ${total} bytes (${speed} kb/s)`}
112
+        {` ${Math.floor((total-now)/speed/1000)} seconds left`}
113
+      </Text>
114
+    </Info>)
75
   })
115
   })
76
-  .then((res) => {
77
-    report(<Assert
78
-      key="upload should success without crashing app"
79
-      expect={filename}
80
-      actual={res.json().name}/>)
116
+  let checkpoint1 = 0
117
+  Timer.setTimeout(() => {
118
+    promise.cancel()
119
+  }, 5000)
120
+  Timer.setTimeout(() => {
121
+    checkpoint1 = bytesWitten
122
+  }, 6000)
123
+  Timer.setTimeout(() => {
124
+    report(<Assert key="data should not write to stream after task is canceled"
125
+      expect={checkpoint1}
126
+      actual={bytesWitten}/>)
81
     done()
127
     done()
128
+  }, 10000)
129
+  promise.then((res) => {
130
+    report(
131
+      <Assert key="task not canceled"
132
+        expected={false}
133
+        actual={true}/>)
134
+  })
135
+  promise.catch((resp) => {
136
+    report(<Assert key="task cancelled rejection should be catachable"
137
+      expect={true}
138
+      actual={true}/>)
82
   })
139
   })
83
 })
140
 })

+ 8
- 8
test/test-init.js View File

58
 })
58
 })
59
 
59
 
60
 
60
 
61
-require('./test-0.1.x-0.4.x')
62
-require('./test-0.5.1')
63
-require('./test-0.5.2')
64
-require('./test-0.6.0')
65
-require('./test-0.6.2')
66
-require('./test-0.6.3')
61
+// require('./test-0.1.x-0.4.x')
62
+// require('./test-0.5.1')
63
+// require('./test-0.5.2')
64
+// require('./test-0.6.0')
65
+// require('./test-0.6.2')
66
+// require('./test-0.6.3')
67
 require('./test-0.7.0')
67
 require('./test-0.7.0')
68
-require('./test-fs')
69
-require('./test-android')
68
+// require('./test-fs')
69
+// require('./test-android')