Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WinJS: Promise chain sometimes sticks after usage of BackgroundUploader class on 512MB WinPhone8.1 Emu

I have strange error that sometimes occurs on my WinJS app on the Windows Phone 8.1 512MB RAM Emulator. I couldn't reproduce it on other Emulator instances or on device.

The execution runs through the promise chain and finishes the following return statement:

  return ( currentUpload = uploadOperation.startAsync() );

After that nothing happens. I set breakpoints at all three functions (success, failure, pending) that are given to the .then definition. None of these three function code will ever be reached when this strange case occurs.

I also put this return statement on a try catch block but there was no exception to catch.

short explanation of code:

  • Background Uploader instance is created (custom headers + PUT method)

  • StorageFile is opened by URI

  • Background uploader prepares upload of that file (definition of uploadOperation)

  • uploadOperation will be started

see full code:

var currentUpload;  // global

 function uploadFile(localFullPath, headers, serverUrl)
 {
    var fileUri = new Windows.Foundation.Uri('ms-appdata:///local' + localFullPath),
        uploader = false;

        try
        {
            uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();
            uploader.method = 'PUT';

            // set headers to uploader
            for (var key in headers)
            {
                if (headers.hasOwnProperty(key))
                    uploader.setRequestHeader(key, headers[key]);
            }
        }
        catch (e)
        {
            // error handling
            return false;
        }

        Windows.Storage.StorageFile.getFileFromApplicationUriAsync(fileUri)
        .then(function success(file)
        {
            return uploader.createUpload(serverUrl, file);
        },
        function failure(error)
        {
            return WinJS.Promise.wrapError('file not found');
        })

        .then(function (uploadOperation)
        {
            if (currentUpload == 'Canceled')
                return WinJS.Promise.wrapError('upload canceled');
            else
                return ( currentUpload = uploadOperation.startAsync() );

        })

        .then(function success(success)
        {
            currentUpload = false;
            // success handling
            return true;
        }, function failure(error)
        {
            currentUpload = false;
            // error handling
            return false;
        }

        }, function pending(status)
        {
            var progress = status.progress,
                percent = Math.round(progress.bytesSent / progress.totalBytesToSend * 100);

            // progress handling
        });
        }

Thanks for any help!

P.S. I also got a deprecated warning, although I'm not using group/TransferGroup on the BackgroundUploader class:

The method Windows.Networking.BackgroundTransfer.IBackgroundTransferBase.put_Group has been deprecated. Group may be altered or unavailable for releases after Windows 8.1. Instead, use TransferGroup.

Maybe it is related to that promise chain error.

like image 514
kerosene Avatar asked Oct 30 '22 17:10

kerosene


1 Answers

Maybe a simple typo error ??
Just check the comments in codes below

var currentUpload;  // global

 function uploadFile(localFullPath, headers, serverUrl)
 {
    var fileUri = new Windows.Foundation.Uri('ms-appdata:///local' + localFullPath),
        uploader = false;

        try
        {
            uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();
            uploader.method = 'PUT';

            // set headers to uploader
            for (var key in headers)
            {
                if (headers.hasOwnProperty(key))
                    uploader.setRequestHeader(key, headers[key]);
            }
        }
        catch (e)
        {
            // error handling
            return false;
        }

        /*

         return something it's a good practice if you want to chain Promises
           |
           |
           V                                                                       */  
        return Windows.Storage.StorageFile.getFileFromApplicationUriAsync(fileUri)
        .then(
          function success(file){
            return uploader.createUpload(serverUrl, file);
          },
          function failure(error){
            return WinJS.Promise.wrapError('file not found');
  //                                        |_____________|  
  // your are rejecting your promise with ---------^
          }
        ).then(
          function (uploadOperation){

  // Just avoid this type of code construction
  // and add brace !
  // adding brace augment readability and prevent errors !

           // where do you set this ??? currentUpload = 'Canceled'
           // is part of winjs ???
           if (currentUpload == 'Canceled') 

           // why not handle your rejected promise ?
           // by something like :
           //if( uploadOperation == 'file not found' )
                return WinJS.Promise.wrapError('upload canceled');
            else
                return ( currentUpload = uploadOperation.startAsync() );
          }
        ).then(
// Promise resolve handler
          function success(success){
            currentUpload = false;
            // success handling
            return true;
          } , 
// Promise reject handler
          function failure(error){
            currentUpload = false;
            // error handling
            return false;
          }
/*        ^  
          |
YOU HAVE HERE A DOUBLE CLOSING BRACE }} ???
 °
 |  WHAT IS THIS PART FOR ??????
 |
 +------+---- Ending uploadFile with successive closing brace !
        |
        |+---------------- Declaration separator
        ||      +--- New function declaration
        ||      |
        VV      V                     */
        }, function pending(status){
            var progress = status.progress,
                percent = Math.round(progress.bytesSent / progress.totalBytesToSend * 100);
            // progress handling
        });
        }

/*
ALL THAT PART ABOVE IS NOT IN THE PROMISE CHAIN 
AND SHOULD BREAK YOUR CODE !!!
HOW HAVE YOU EVER COULD RUN THIS ???
*/

maybe it miss a part of your code to be sure of that, because in this state your code must break !


Maybe an adjustement could be :

var currentUpload;  // global

function uploadFile(localFullPath, headers, serverUrl)
{
  var fileUri = new Windows.Foundation.Uri('ms-appdata:///local' + localFullPath),
      uploader = false;

  try
  {
    uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();
    uploader.method = 'PUT';

    // set headers to uploader
    for (var key in headers)
    {
      if (headers.hasOwnProperty(key))
        uploader.setRequestHeader(key, headers[key]);
    }
  }
  catch (e)
  {
    // error handling
    return false;
  }

  /*

  return something it's a good practice if you want to chain Promises
    |
    |
    V                                                                     */  
  return Windows.Storage.StorageFile.getFileFromApplicationUriAsync(fileUri)
  .then(
    function success(file){
      return uploader.createUpload(serverUrl, file);
    },
    function failure(error){
      return WinJS.Promise.wrapError('file not found');// O|--------+
    }//                                                             |
  ).then(//                                                         |
    function (uploadOperation){//  O|-------------------------------|
      //                                                            |
      // Just avoid this type of code construction                  |
      // and add brace !                                            |
      // adding brace augment readability and prevent errors !      |
      //                                                            |   
      // EDIT                                                       |
      //if (currentUpload == 'Canceled') { // <--- add brace        |
      if (uploadOperation == 'file not found') { //<---add brace <--+ 

        return WinJS.Promise.wrapError('upload canceled');

      } else { // <---- add braces

        // even if it is valid
        // avoid assignement like that
        // so subtil to read / understand / debug ...
        // return ( currentUpload = uploadOperation.startAsync() );

        currentUpload = uploadOperation.startAsync();
        // maybe debug here ?
        console.log('currentUpload : ' + currentUpload );
        return currentUpload;

      } // <---- add brace
    }
  ).then(
    function success(success){
      currentUpload = false;
      // success handling
      return true;
    } , 
    function failure(error){
      currentUpload = false;
      // error handling
      return false;
    } ,
    function pending(status){
      var progress = status.progress,
          percent = Math.round(progress.bytesSent / progress.totalBytesToSend * 100);
      // progress handling
    }
  ).done( // it is always a good thing to have a final catcher !!
    function(){
      // things are ok !
      console.log('ok');
    },
    function(err){
      // make something with your error better than
      alert(err);
      console.log('ko');

    }
  );
}

EDIT

Looking further (i do not use winjs), there is something to be clarified :

.then(
  function success(file) {
    return uploader.createUpload(serverUrl, file);
  },
  function failure(error) {
    return WinJS.Promise.wrapError('file not found');

  }
).then(
  function(uploadOperation) {

    if (currentUpload == 'Canceled')
      return WinJS.Promise.wrapError('upload canceled');
    else
      return (currentUpload = uploadOperation.startAsync());
  }
).

where are you setting this :
currentUpload = 'Canceled'
You are checking that but i'am pretty sure this part of code is never reached.
Before that your reject your promise with :
return WinJS.Promise.wrapError('file not found');
maybe the next then should handle someting like that :

.then(
  function success(file) {
    return uploader.createUpload(serverUrl, file);
  },
  function failure(error) {
    return WinJS.Promise.wrapError('file not found');

  }
).then(
  function(uploadOperation) {

    if (uploadOperation == 'file not found')
      return WinJS.Promise.wrapError('upload canceled');
    else
      return (currentUpload = uploadOperation.startAsync());
  }
)

I hope this will help you.

like image 116
Anonymous0day Avatar answered Nov 08 '22 03:11

Anonymous0day