1

I'm trying to generalize a script that encrypts forms using OpenPGP libraries. I got some troubles with the client-side code (Javascript) :

var working = formID.elements[0];
var counter = 0;

while (working) {
    encrypt(working.value).then(function(encrypted_msg) {
        console.log("processing");
        working.value = encrypted_msg;
    });
    console.log("assuming processed");
    var counter = counter + 1;
    var working = formID.elements[counter];
}

The following code should take each form element and encrypt its value. However, the while loop doesn't wait for the asynchronous encrypt() function to be resolved.

I think i need to use promises in this case, but i have no idea how and the few tutorials didn't work in a while loop.

Help ?

7
  • are you using any framework angular/react for frontend or pure javascript? Commented Sep 28, 2016 at 16:51
  • @AkashBhandwalkar Only pure javascript and JQuery. Commented Sep 28, 2016 at 16:54
  • I answered. I hope it will work! Commented Sep 28, 2016 at 16:56
  • 1
    You can use recursive function also. Like call function on success of first asynchronus call Commented Sep 28, 2016 at 16:58
  • @Square, is the next form element encryption dependent on the previous? Commented Sep 28, 2016 at 17:03

2 Answers 2

2

Probably can be used list of jQuery deferreds, something like this:

var deferreds = [];

$.each(formID.elements, function(key, working){

    var deferred = $.Deferred();
    deferreds.push(deferred);

    encrypt(working.value).then(function(encrypted_msg) {
        console.log("processing");
        working.value = encrypted_msg;
        deferred.resolve();
    });

});

$.when.apply( $, deferreds ).done(function(){
    console.log( 'after all encryptions!' );
});

Of course, can be used native Promise object instead $.Deferred, however I think $.Deferred is more cross-browser way.

UPD2:

Improved answer based on native Promise and Promise.resolve() (thanks to @Bergi). For the case when encrypt() returns correct promise, method Promise.resolve() can be skipped.

var promises = [];

$.each(formID.elements, function(key, working){

    var promise = Promise.resolve(encrypt(working.value))
        .then(function(encrypted_msg) {
            console.log("processing");
            working.value = encrypted_msg;
        });

    promises.push(promise);

});

Promise.all(promises).then(function(){
    console.log( 'after all encryptions!' );
});
Sign up to request clarification or add additional context in comments.

4 Comments

In theory, yes, but avoid the deferred antipattern!
@Bergi Yes, it is bad practice to create excess deferreds/promices. But I don't know what object returns encrypt method and how it will work with $.when() or Promise.all(). The fact that this object contains .then method, not much to say about him. I updated answer without antipattern.
@IStranger If you don't know what it returns, you can always use Promise.resolve(encrypt(…)) (or $.when(encrypt(…)) in jQuery), that's what they are for.
@Bergi Thanks, it is awesome method). I like similar methods that allows to unify type without if statements and additional abstract layers. I improved answer using it.
1
var iterator = [];
for (var counter = 0; counter < formID.elements.length; counter++) {
    var working = formID.elements[counter];
    iterator.push(encrypt(working.value));
}

Promise.all(iterator)
.then(fumction(data){
    //Here you have all data
})

You can synchronize your operation like this way. By collecting all asynchronus value references and point to them when they have data.

In case your data is dependent.

function myfunction(previousValue){
    if(breaking Condition){
        return Promise.resolve();
    }
    return encrypt(working.value).then(function(encrypted_msg) {
        working.value = encrypted_msg;
        return myfunction(working);
    });
}

2 Comments

One problem tho, I need to pass the working var to the iterator too. How can i achieve that ?
Had an error, undefined working var. Still trying to make it work, tho.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.