Browse Source

ref(RTC): RTCRtpSender.setParameters promise

Handle the promise returned by RTCRtpSender.setParameters.
dev1
paweldomas 5 years ago
parent
commit
cc363c5664
3 changed files with 107 additions and 111 deletions
  1. 32
    35
      modules/RTC/TPCUtils.js
  2. 38
    19
      modules/RTC/TraceablePeerConnection.js
  3. 37
    57
      modules/xmpp/JingleSessionPC.js

+ 32
- 35
modules/RTC/TPCUtils.js View File

@@ -207,8 +207,7 @@ export class TPCUtils {
207 207
     /**
208 208
     * Adds {@link JitsiLocalTrack} to the WebRTC peerconnection for the first time.
209 209
     * @param {JitsiLocalTrack} track - track to be added to the peerconnection.
210
-    * @returns {boolean} Returns true if the operation is successful,
211
-    * false otherwise.
210
+    * @returns {void}
212 211
     */
213 212
     addTrack(localTrack, isInitiator = true) {
214 213
         const track = localTrack.getTrack();
@@ -242,8 +241,7 @@ export class TPCUtils {
242 241
     /**
243 242
      * Adds a track on the RTCRtpSender as part of the unmute operation.
244 243
      * @param {JitsiLocalTrack} localTrack - track to be unmuted.
245
-     * @returns {Promise<boolean>} - Promise that resolves to false if unmute
246
-     * operation is successful, a reject otherwise.
244
+     * @returns {Promise<void>} - resolved when done.
247 245
      */
248 246
     addTrackUnmute(localTrack) {
249 247
         const mediaType = localTrack.getType();
@@ -266,26 +264,26 @@ export class TPCUtils {
266 264
 
267 265
             if (stream) {
268 266
                 this.pc.peerconnection.addStream(localTrack.getOriginalStream());
269
-                this.setEncodings(localTrack);
270
-                this.pc.localTracks.set(localTrack.rtcId, localTrack);
271
-                transceiver.direction = 'sendrecv';
272 267
 
273
-                // Construct the simulcast stream constraints for the newly added track.
274
-                if (localTrack.isVideoTrack()
275
-                    && localTrack.videoType === VideoType.CAMERA
276
-                    && this.pc.isSimulcastOn()) {
277
-                    this.setSimulcastStreamConstraints(localTrack.getTrack());
278
-                }
268
+                return this.setEncodings(localTrack).then(() => {
269
+                    this.pc.localTracks.set(localTrack.rtcId, localTrack);
270
+                    transceiver.direction = 'sendrecv';
271
+
272
+                    // Construct the simulcast stream constraints for the newly added track.
273
+                    if (localTrack.isVideoTrack()
274
+                        && localTrack.videoType === VideoType.CAMERA
275
+                        && this.pc.isSimulcastOn()) {
276
+                        this.setSimulcastStreamConstraints(localTrack.getTrack());
277
+                    }
278
+                });
279 279
             }
280 280
 
281
-            return Promise.resolve(false);
281
+            return Promise.resolve();
282 282
         }
283 283
 
284 284
         return transceiver.sender.replaceTrack(track)
285 285
             .then(() => {
286 286
                 this.pc.localTracks.set(localTrack.rtcId, localTrack);
287
-
288
-                return Promise.resolve(false);
289 287
             });
290 288
     }
291 289
 
@@ -318,9 +316,7 @@ export class TPCUtils {
318 316
      * Replaces the existing track on a RTCRtpSender with the given track.
319 317
      * @param {JitsiLocalTrack} oldTrack - existing track on the sender that needs to be removed.
320 318
      * @param {JitsiLocalTrack} newTrack - new track that needs to be added to the sender.
321
-     * @returns {Promise<false>} Promise that resolves with false as we don't want
322
-     * renegotiation to be triggered automatically after this operation. Renegotiation is
323
-     * done when the browser fires the negotiationeeded event.
319
+     * @returns {Promise<void>} - resolved when done.
324 320
      */
325 321
     replaceTrack(oldTrack, newTrack) {
326 322
         if (oldTrack && newTrack) {
@@ -361,15 +357,15 @@ export class TPCUtils {
361 357
         } else if (newTrack && !oldTrack) {
362 358
             const ssrc = this.pc.localSSRCs.get(newTrack.rtcId);
363 359
 
364
-            if (!this.addTrackUnmute(newTrack)) {
365
-                return Promise.reject(new Error('replace track failed'));
366
-            }
367
-            newTrack.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED, newTrack);
368
-            this.pc.localTracks.set(newTrack.rtcId, newTrack);
369
-            this.pc.localSSRCs.set(newTrack.rtcId, ssrc);
360
+            this.addTrackUnmute(newTrack)
361
+                .then(() => {
362
+                    newTrack.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED, newTrack);
363
+                    this.pc.localTracks.set(newTrack.rtcId, newTrack);
364
+                    this.pc.localSSRCs.set(newTrack.rtcId, ssrc);
365
+                });
370 366
         }
371 367
 
372
-        return Promise.resolve(false);
368
+        return Promise.resolve();
373 369
     }
374 370
 
375 371
     /**
@@ -379,8 +375,7 @@ export class TPCUtils {
379 375
     * the connection should be kept alive.
380 376
     * @param {boolean} active - true to enable audio media transmission or
381 377
     * false to disable.
382
-    * @returns {false} - returns false always so that renegotiation is not automatically
383
-    * triggered after this operation.
378
+    * @returns {Promise<void>} - resolved when done.
384 379
     */
385 380
     setAudioTransferActive(active) {
386 381
         return this.setMediaTransferActive('audio', active);
@@ -390,6 +385,7 @@ export class TPCUtils {
390 385
      * Set the simulcast stream encoding properties on the RTCRtpSender.
391 386
      * @param {JitsiLocalTrack} track - the current track in use for which
392 387
      * the encodings are to be set.
388
+     * @returns {Promise<void>} - resolved when done.
393 389
      */
394 390
     setEncodings(track) {
395 391
         const transceiver = this.pc.peerconnection.getTransceivers()
@@ -397,7 +393,8 @@ export class TPCUtils {
397 393
         const parameters = transceiver.sender.getParameters();
398 394
 
399 395
         parameters.encodings = this._getStreamEncodings(track);
400
-        transceiver.sender.setParameters(parameters);
396
+
397
+        return transceiver.sender.setParameters(parameters);
401 398
     }
402 399
 
403 400
     /**
@@ -406,8 +403,7 @@ export class TPCUtils {
406 403
      * @param {String} mediaType - 'audio' or 'video'
407 404
      * @param {boolean} active - true to enable media transmission or false
408 405
      * to disable.
409
-     * @returns {false} - returns false always so that renegotiation is not automatically
410
-     * triggered after this operation
406
+     * @returns {Promise<void>} - resolved when done.
411 407
      */
412 408
     setMediaTransferActive(mediaType, active) {
413 409
         const transceivers = this.pc.peerconnection.getTransceivers()
@@ -415,6 +411,8 @@ export class TPCUtils {
415 411
         const localTracks = Array.from(this.pc.localTracks.values())
416 412
             .filter(track => track.getType() === mediaType);
417 413
 
414
+        const setParamPromises = [];
415
+
418 416
         if (active) {
419 417
             transceivers.forEach(transceiver => {
420 418
                 if (localTracks.length) {
@@ -425,7 +423,7 @@ export class TPCUtils {
425 423
                         parameters.encodings.forEach(encoding => {
426 424
                             encoding.active = true;
427 425
                         });
428
-                        transceiver.sender.setParameters(parameters);
426
+                        setParamPromises.push(transceiver.sender.setParameters(parameters));
429 427
                     }
430 428
                 } else {
431 429
                     transceiver.direction = 'recvonly';
@@ -437,7 +435,7 @@ export class TPCUtils {
437 435
             });
438 436
         }
439 437
 
440
-        return false;
438
+        return Promise.all(setParamPromises);
441 439
     }
442 440
 
443 441
     /**
@@ -447,8 +445,7 @@ export class TPCUtils {
447 445
     * the connection should be kept alive.
448 446
     * @param {boolean} active - true to enable video media transmission or
449 447
     * false to disable.
450
-    * @returns {false} - returns false always so that renegotiation is not automatically
451
-    * triggered after this operation.
448
+    * @returns {Promise<void>} - resolved when done.
452 449
     */
453 450
     setVideoTransferActive(active) {
454 451
         return this.setMediaTransferActive('video', active);

+ 38
- 19
modules/RTC/TraceablePeerConnection.js View File

@@ -1480,6 +1480,7 @@ TraceablePeerConnection.prototype.containsTrack = function(track) {
1480 1480
 /**
1481 1481
  * Add {@link JitsiLocalTrack} to this TPC.
1482 1482
  * @param {JitsiLocalTrack} track
1483
+ * @returns {Promise<void>} - resolved when done.
1483 1484
  */
1484 1485
 TraceablePeerConnection.prototype.addTrack = function(track, isInitiator = false) {
1485 1486
     const rtcId = track.rtcId;
@@ -1487,14 +1488,15 @@ TraceablePeerConnection.prototype.addTrack = function(track, isInitiator = false
1487 1488
     logger.info(`add ${track} to: ${this}`);
1488 1489
 
1489 1490
     if (this.localTracks.has(rtcId)) {
1490
-        logger.error(`${track} is already in ${this}`);
1491 1491
 
1492
-        return;
1492
+        return Promise.reject(new Error(`${track} is already in ${this}`));
1493 1493
     }
1494 1494
 
1495 1495
     this.localTracks.set(rtcId, track);
1496 1496
     if (browser.usesUnifiedPlan() && isInitiator) {
1497
-        return this.tpcUtils.addTrack(track, isInitiator);
1497
+        this.tpcUtils.addTrack(track, isInitiator);
1498
+
1499
+        return Promise.resolve();
1498 1500
     }
1499 1501
 
1500 1502
     const webrtcStream = track.getOriginalStream();
@@ -1506,7 +1508,7 @@ TraceablePeerConnection.prototype.addTrack = function(track, isInitiator = false
1506 1508
     } else if (!browser.doesVideoMuteByStreamRemove()
1507 1509
                 || track.isAudioTrack()
1508 1510
                 || (track.isVideoTrack() && !track.isMuted())) {
1509
-        logger.error(`${this} no WebRTC stream for: ${track}`);
1511
+        return Promise.reject(new Error(`${this} no WebRTC stream for: ${track}`));
1510 1512
     }
1511 1513
 
1512 1514
     // Muted video tracks do not have WebRTC stream
@@ -1538,14 +1540,18 @@ TraceablePeerConnection.prototype.addTrack = function(track, isInitiator = false
1538 1540
         }
1539 1541
     }
1540 1542
 
1543
+    let promiseChain = Promise.resolve();
1544
+
1541 1545
     if (browser.usesUnifiedPlan() && !browser.usesSdpMungingForSimulcast()) {
1542
-        this.tpcUtils.setEncodings(track);
1546
+        promiseChain = this.tpcUtils.setEncodings(track);
1543 1547
     }
1544 1548
 
1545 1549
     // Construct the simulcast stream constraints for the newly added track.
1546 1550
     if (track.isVideoTrack() && track.videoType === VideoType.CAMERA && this.isSimulcastOn()) {
1547 1551
         this.tpcUtils.setSimulcastStreamConstraints(track.getTrack());
1548 1552
     }
1553
+
1554
+    return promiseChain;
1549 1555
 };
1550 1556
 
1551 1557
 /**
@@ -1705,16 +1711,20 @@ TraceablePeerConnection.prototype.findSenderForTrack = function(track) {
1705 1711
  */
1706 1712
 TraceablePeerConnection.prototype.replaceTrack = function(oldTrack, newTrack) {
1707 1713
     if (browser.usesUnifiedPlan()) {
1708
-        return this.tpcUtils.replaceTrack(oldTrack, newTrack);
1714
+        return this.tpcUtils.replaceTrack(oldTrack, newTrack)
1715
+            .then(() => false);
1709 1716
     }
1717
+
1718
+    let promiseChain = Promise.resolve();
1719
+
1710 1720
     if (oldTrack) {
1711 1721
         this.removeTrack(oldTrack);
1712 1722
     }
1713 1723
     if (newTrack) {
1714
-        this.addTrack(newTrack);
1724
+        promiseChain = this.addTrack(newTrack);
1715 1725
     }
1716 1726
 
1717
-    return Promise.resolve(true);
1727
+    return promiseChain.then(() => true);
1718 1728
 };
1719 1729
 
1720 1730
 /**
@@ -1926,7 +1936,8 @@ TraceablePeerConnection.prototype.setLocalDescription = function(description) {
1926 1936
 TraceablePeerConnection.prototype.setAudioTransferActive = function(active) {
1927 1937
     logger.debug(`${this} audio transfer active: ${active}`);
1928 1938
     if (browser.usesUnifiedPlan()) {
1929
-        return this.tpcUtils.setAudioTransferActive(active);
1939
+        return this.tpcUtils.setAudioTransferActive(active)
1940
+            .then(() => false);
1930 1941
     }
1931 1942
     const changed = this.audioTransferActive !== active;
1932 1943
 
@@ -1940,24 +1951,24 @@ TraceablePeerConnection.prototype.setAudioTransferActive = function(active) {
1940 1951
  * resolution or framerate will be preferred when bandwidth or cpu is constrained.
1941 1952
  * Sets it to 'maintain-framerate' when a camera track is added to the pc, sets it
1942 1953
  * to 'maintain-resolution' when a desktop track is being shared instead.
1943
- * @returns {void}
1954
+ * @returns {Promise<void>}
1944 1955
  */
1945 1956
 TraceablePeerConnection.prototype.setSenderVideoDegradationPreference = function() {
1946 1957
     if (!this.peerconnection.getSenders) {
1947 1958
         logger.debug('Browser does not support RTCRtpSender');
1948 1959
 
1949
-        return;
1960
+        return Promise.resolve();
1950 1961
     }
1951 1962
     const localVideoTrack = Array.from(this.localTracks.values()).find(t => t.isVideoTrack());
1952 1963
     const videoSender = this.findSenderByKind(MediaType.VIDEO);
1953 1964
 
1954 1965
     if (!videoSender) {
1955
-        return;
1966
+        return Promise.resolve();
1956 1967
     }
1957 1968
     const parameters = videoSender.getParameters();
1958 1969
 
1959 1970
     if (!parameters.encodings || !parameters.encodings.length) {
1960
-        return;
1971
+        return Promise.resolve();
1961 1972
     }
1962 1973
     for (const encoding in parameters.encodings) {
1963 1974
         if (parameters.encodings.hasOwnProperty(encoding)) {
@@ -1969,7 +1980,8 @@ TraceablePeerConnection.prototype.setSenderVideoDegradationPreference = function
1969 1980
             parameters.encodings[encoding].degradationPreference = preference;
1970 1981
         }
1971 1982
     }
1972
-    videoSender.setParameters(parameters);
1983
+
1984
+    return videoSender.setParameters(parameters);
1973 1985
 };
1974 1986
 
1975 1987
 /**
@@ -1979,6 +1991,7 @@ TraceablePeerConnection.prototype.setSenderVideoDegradationPreference = function
1979 1991
  * simulcast is implemented.
1980 1992
  * @param {JitsiLocalTrack} localTrack - the local track whose
1981 1993
  * max bitrate is to be configured.
1994
+ * @returns {Promise<void>}
1982 1995
  */
1983 1996
 TraceablePeerConnection.prototype.setMaxBitRate = function(localTrack = null) {
1984 1997
     if (!localTrack) {
@@ -1986,7 +1999,7 @@ TraceablePeerConnection.prototype.setMaxBitRate = function(localTrack = null) {
1986 1999
         localTrack = Array.from(this.localTracks.values()).find(t => t.isVideoTrack());
1987 2000
 
1988 2001
         if (!localTrack) {
1989
-            return;
2002
+            return Promise.resolve();
1990 2003
         }
1991 2004
     }
1992 2005
     const trackId = localTrack.track.id;
@@ -1999,17 +2012,19 @@ TraceablePeerConnection.prototype.setMaxBitRate = function(localTrack = null) {
1999 2012
     if (!((this.options.videoQuality && this.options.videoQuality.maxBitratesVideo)
2000 2013
         || (browser.usesPlanB() && this.options.capScreenshareBitrate && videoType === VideoType.DESKTOP))
2001 2014
         || browser.usesUnifiedPlan()) {
2002
-        return;
2015
+        return Promise.resolve();
2003 2016
     }
2004 2017
 
2005 2018
     if (!this.peerconnection.getSenders) {
2006 2019
         logger.debug('Browser doesn\'t support RTCRtpSender');
2007 2020
 
2008
-        return;
2021
+        return Promise.resolve();
2009 2022
     }
2010 2023
     const presenterEnabled = localTrack._originalStream
2011 2024
         && localTrack._originalStream.id !== localTrack.getStreamId();
2012 2025
 
2026
+    const setSenderParamPromises = [];
2027
+
2013 2028
     this.peerconnection.getSenders()
2014 2029
         .filter(s => s.track && s.track.id === trackId)
2015 2030
         .forEach(sender => {
@@ -2037,12 +2052,15 @@ TraceablePeerConnection.prototype.setMaxBitRate = function(localTrack = null) {
2037 2052
                                     : HD_BITRATE;
2038 2053
                     }
2039 2054
                 }
2040
-                sender.setParameters(parameters);
2055
+                setSenderParamPromises.push(sender.setParameters(parameters));
2041 2056
             } catch (err) {
2042 2057
                 logger.error('Browser does not support getParameters/setParamters '
2043 2058
                     + 'or setting max bitrate on the encodings: ', err);
2044 2059
             }
2045 2060
         });
2061
+
2062
+    return Promise.all(setSenderParamPromises)
2063
+        .then(() => Promise.resolve());
2046 2064
 };
2047 2065
 
2048 2066
 TraceablePeerConnection.prototype.setRemoteDescription = function(description) {
@@ -2196,7 +2214,8 @@ TraceablePeerConnection.prototype.setSenderVideoConstraint = function(frameHeigh
2196 2214
 TraceablePeerConnection.prototype.setVideoTransferActive = function(active) {
2197 2215
     logger.debug(`${this} video transfer active: ${active}`);
2198 2216
     if (browser.usesUnifiedPlan()) {
2199
-        return this.tpcUtils.setVideoTransferActive(active);
2217
+        return this.tpcUtils.setVideoTransferActive(active)
2218
+            .then(() => false);
2200 2219
     }
2201 2220
     const changed = this.videoTransferActive !== active;
2202 2221
 

+ 37
- 57
modules/xmpp/JingleSessionPC.js View File

@@ -926,36 +926,26 @@ export default class JingleSessionPC extends JingleSession {
926 926
      * added, before the offer/answer cycle executes (for the local track
927 927
      * addition to be an atomic operation together with the offer/answer).
928 928
      */
929
-    invite(localTracks) {
929
+    invite(localTracks = []) {
930 930
         if (!this.isInitiator) {
931 931
             throw new Error('Trying to invite from the responder session');
932 932
         }
933 933
         const workFunction = finishedCallback => {
934
+            const addTracks = [];
935
+
934 936
             for (const localTrack of localTracks) {
935
-                this.peerconnection.addTrack(localTrack, true /* isInitiator */);
937
+                addTracks.push(this.peerconnection.addTrack(localTrack, true /* isInitiator */));
936 938
             }
937
-            this.peerconnection.createOffer(this.mediaConstraints)
938
-                .then(offerSdp => {
939
-                    this.peerconnection.setLocalDescription(offerSdp)
940
-                        .then(() => {
941
-                            // NOTE that the offer is obtained from
942
-                            // the localDescription getter as it needs to go
943
-                            // though the transformation chain.
944
-                            this.sendSessionInitiate(
945
-                                this.peerconnection.localDescription.sdp);
946
-                            finishedCallback();
947
-                        }, error => {
948
-                            logger.error(
949
-                                'Failed to set local SDP', error, offerSdp);
950
-                            finishedCallback(error);
951
-                        });
952
-                }, error => {
953
-                    logger.error(
954
-                        'Failed to create an offer',
955
-                        error,
956
-                        this.mediaConstraints);
957
-                    finishedCallback(error);
958
-                });
939
+
940
+            Promise.all(addTracks)
941
+                .then(() => this.peerconnection.createOffer(this.mediaConstraints))
942
+                .then(offerSdp => this.peerconnection.setLocalDescription(offerSdp))
943
+                .then(() => {
944
+                    // NOTE that the offer is obtained from the localDescription getter as it needs to go though
945
+                    // the transformation chain.
946
+                    this.sendSessionInitiate(this.peerconnection.localDescription.sdp);
947
+                })
948
+                .then(() => finishedCallback(), error => finishedCallback(error));
959 949
         };
960 950
 
961 951
         this.modificationQueue.push(
@@ -1038,13 +1028,12 @@ export default class JingleSessionPC extends JingleSession {
1038 1028
      * executes (for the local track addition to be an atomic operation together
1039 1029
      * with the offer/answer).
1040 1030
      */
1041
-    setOfferAnswerCycle(jingleOfferAnswerIq, success, failure, localTracks) {
1031
+    setOfferAnswerCycle(jingleOfferAnswerIq, success, failure, localTracks = []) {
1042 1032
         const workFunction = finishedCallback => {
1033
+            const addTracks = [];
1043 1034
 
1044
-            if (localTracks) {
1045
-                for (const track of localTracks) {
1046
-                    this.peerconnection.addTrack(track);
1047
-                }
1035
+            for (const track of localTracks) {
1036
+                addTracks.push(this.peerconnection.addTrack(track));
1048 1037
             }
1049 1038
 
1050 1039
             const newRemoteSdp
@@ -1062,7 +1051,8 @@ export default class JingleSessionPC extends JingleSession {
1062 1051
                 this._bridgeSessionId = bridgeSessionId;
1063 1052
             }
1064 1053
 
1065
-            this._renegotiate(newRemoteSdp.raw)
1054
+            Promise.all(addTracks)
1055
+                .then(() => this._renegotiate(newRemoteSdp.raw))
1066 1056
                 .then(() => {
1067 1057
                     if (this.state === JingleSessionState.PENDING) {
1068 1058
                         this.state = JingleSessionState.ACTIVE;
@@ -1097,16 +1087,8 @@ export default class JingleSessionPC extends JingleSession {
1097 1087
                         this.notifyMySSRCUpdate(
1098 1088
                             new SDP(oldLocalSdp), newLocalSdp);
1099 1089
                     }
1100
-
1101
-                    finishedCallback();
1102
-                }, error => {
1103
-                    logger.error(
1104
-                        `Error renegotiating after setting new remote ${
1105
-                            this.isInitiator ? 'answer: ' : 'offer: '}${error}`,
1106
-                        newRemoteSdp);
1107
-
1108
-                    finishedCallback(error);
1109
-                });
1090
+                })
1091
+                .then(() => finishedCallback(), error => finishedCallback(error));
1110 1092
         };
1111 1093
 
1112 1094
         this.modificationQueue.push(
@@ -1919,29 +1901,27 @@ export default class JingleSessionPC extends JingleSession {
1919 1901
                             const newLocalSDP = new SDP(this.peerconnection.localDescription.sdp);
1920 1902
 
1921 1903
                             this.notifyMySSRCUpdate(new SDP(oldLocalSdp), newLocalSDP);
1922
-                        },
1923
-                        finishedCallback /* will be called with en error */);
1904
+                        });
1924 1905
                     }
1925 1906
 
1926
-                    promise.then(() => {
1907
+                    return promise.then(() => {
1927 1908
                         if (newTrack && newTrack.isVideoTrack()) {
1909
+                            // FIXME set all sender parameters in one go?
1928 1910
                             // Set the degradation preference on the new video sender.
1929
-                            this.peerconnection.setSenderVideoDegradationPreference();
1930
-
1931
-                            // Apply the cached video constraints on the new video sender.
1932
-                            this.peerconnection.setSenderVideoConstraint();
1933
-
1934
-                            // Configure max bitrate on the video sender when media is routed through JVB.
1935
-                            if (!this.isP2P) {
1936
-                                this.peerconnection.setMaxBitRate(newTrack);
1937
-                            }
1911
+                            return this.peerconnection.setSenderVideoDegradationPreference()
1912
+
1913
+                                // Apply the cached video constraints on the new video sender.
1914
+                                .then(() => this.peerconnection.setSenderVideoConstraint())
1915
+                                .then(() => {
1916
+                                    // Configure max bitrate on the video sender when media is routed through JVB.
1917
+                                    if (!this.isP2P) {
1918
+                                        return this.peerconnection.setMaxBitRate(newTrack);
1919
+                                    }
1920
+                                });
1938 1921
                         }
1939
-                        finishedCallback();
1940
-                    }, finishedCallback /* will be called with en error */);
1922
+                    });
1941 1923
                 })
1942
-                .catch(err => {
1943
-                    finishedCallback(err);
1944
-                });
1924
+                .then(() => finishedCallback(), error => finishedCallback(error));
1945 1925
         };
1946 1926
 
1947 1927
         return new Promise((resolve, reject) => {

Loading…
Cancel
Save