1

I create a simple mailer for our updates into client emails, But how can I send the data one by one and process each data on server side

html:


<p class="response"></p>

<form id="send_updates">
    {% csrf_token %}
    <textarea name="mail-list" class="mails" id="mails"></textarea>
    <button type="submit"> start sends </button>
</form>

javascript:

let mails = $('#mails').val().split('\n');
for(let i = 0; i <= cc.length; i++){
    $.ajax({
        cache: false,
        type: 'post',
        url: "{% url 'send_mail' %}",
        data: {'email': mails[i]},
        async: true,
        beforeSend:function(xhr, settings){
            xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
        };
        success: function(data){
            if (data.success) == true{
                $('.response').append(mails[i] + ' sent!')
            }else{
                $('.response').append(mails[i] + ' not sent!')
            };
        }
    });

BUT! It Sends All Request without waiting if it Success or Not

EDIT:

We Want to Monitor One By One If That Email is Send Successfully or Not!

2
  • 3
    Well that makes perfect sense, since $.ajax(..) indeed just simply sends a request, the success: ... is a callback that is done after the request was succesfull. Here it is definitely possible that the values will be appended in a different order than how you submitted it. Commented Sep 7, 2019 at 7:48
  • look for snippets like sequential ajax, or better have a master mailer where you send all data and the BE then loops and process, that way you will have one single http request, saves bandwidth and too much to and fro communication between client server Commented Sep 7, 2019 at 7:56

3 Answers 3

1

Try setting

    async: false,

as shown below:

    let mails = $('#mails').val().split('\n');
    for(let i = 0; i <= cc.length; i++){
    $.ajax({
      cache: false,
      type: 'post',
      url: "{% url 'send_mail' %}",
      data: {'email': mails[i]},
      async: false,
      beforeSend:function(xhr, settings){
        xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
      };
      success: function(data){
        if (data.success) == true{
            $('.response').append(mails[i] + ' sent!')
        }else{
            $('.response').append(mails[i] + ' not sent!')
        };
      }
     });

Refer What does "async: false" do in jQuery.ajax()?

Sign up to request clarification or add additional context in comments.

2 Comments

I thought this is be ok, But it proccess all first the request then return it once!
What I want is When the Email is currenly proccessing on back end, It shows on the client side then show the results if success or not
1

You can use the async/await .

function getData(ajaxurl , mail) { 
        return $.ajax({
            cache: false,
            type: 'post',
            url: "{% url 'send_mail' %}" /*instead `ajaxurl`*/,
            data: {'email': mail},
            beforeSend:function(xhr, settings){
                xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
            },
            success: function(data){
                if (data.success == true){
                    $('.response').append(mails[i] + ' sent!');
                }else{
                    $('.response').append(mails[i] + ' not sent!')
                }
            }
        });
    };

    async function test(mail){
        try {
            const res = await getData('https://api.icndb.com/jokes/random' , mail);
            console.log(res);
        } catch(err) {
            console.log(err);
        }
    }



    var mails = $('#mails').val().split('\n');
    for(let i = 0; i <= cc.length; i++){
        var mail = mails[i];
        test(mail);
    }

Try out this method . Here the test() function is async and will await for getData() function to complete everytime . Through this , you will achieve your goal .

Comments

1

If you need to update the UI as they happen:

function fetchNextMail(mails) {
  const nextMail = mails.shift();
  $.ajax({
    type: "get",
    url:
      "https://jsonplaceholder.typicode.com/todos/1"
  }).then(res => {
    console.log(Object.keys(res));
    console.log(mails.length);
    mails.length && fetchNextMail(mails);
  });
}

fetchNextMail(["x", "y", "z"]);

If you can wait for all of them to finish to update the UI, you can use Promise.all:

Promise.all(
  ["x", "y", "z"].map(mail => {
    return $.ajax({
      type: "get",
      url: "https://jsonplaceholder.typicode.com/todos/1"
    });
  })
).then(results => {
  // results[0], results[1] and results[2]
  console.log(results.length);
});

A working example can be found here: https://codesandbox.io/s/jquery-playground-i2vb4

Comments

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.