2016-11-14 2 views
0

Прежде чем я начну, я хочу упомянуть, что у меня нет большого опыта работы с обещаниями/отложенными объектами в JavaScript.

То, что я пытаюсь достичь, - это когда пользователь нажимает кнопку, он выполняет несколько запросов $.getJSON, обрабатывает ответы и соответственно обновляет страницу.

Я также должен уведомить пользователя, когда все эти запросы были завершены, здесь метод connect меня который обрабатывает первую часть я говорил о том:

function connect(row) { 
    return new Promise(function(resolve, reject) { 
     var trees = $("#selectedTree").val(); 
     var employee_id = row.attr("rel"); 

     var columns = row.children(); 
     var emailColumn = $(columns[1]); 
     var firstNameColumn = $(columns[2]); 
     var lastNameColumn = $(columns[3]); 
     var jobTitleColumn = $(columns[4]); 
     var statusColumn = $(columns[5]); 
     var actionsColumn = $(columns[6]); 

     actionsColumn.html("<span class='spinner'><i class='fa fa-spinner fa-spin'></i></span>"); 
     $.getJSON("functions/connect_with.php", { 
      employee_id: employee_id, 
      trees: trees 
     }, function(response) { 
      emailColumn.html(response.message.person.email); 
      actionsColumn.html("<i class='text-success fa fa-check'></i>"); 
      if(response.success) { 
       firstNameColumn.html(response.message.person.name.givenName); 
       lastNameColumn.html(response.message.person.name.familyName); 
       jobTitleColumn.html(response.message.person.employment.title); 
      } 
      statusColumn.html("<i class='text-success fa fa-sitemap'></i>"); 
      resolve(true); 
     }); 
    }); 
} 

И это то, что происходит, когда пользователь нажимает кнопку сказал:

$("#connectAll").click(function() { 
     alert("OFF WE GO"); 
     $(this).hide(); 
     var methods = []; 
     $(".staffMember input:checked").each(function(index, checkbox) { 
      checkbox = $(checkbox); 
      var row = checkbox.parents("tr"); 
      methods.push(connect(row)); 
     }); 
     $.when.apply($, methods).then(function() { 
      alert("WE DID IT MOM"); 
      $("#connectAll").show(); 
     }); 
    }); 

Однако оба оповещения отправляются сразу после того, как друг с другом, и не дожидаясь просьбы, чтобы закончить. Я пробовал другие способы сделать это, и я не могу понять, что это правильно.

+3

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all – Hackerman

+0

Ну, дерьмо. Спасибо, похоже, сделали трюк. Благодаря! – ThePerplexedOne

+0

Действительно хорошая ссылка @Хакерман, я не знал об этом – George

ответ

1

Вам не нужно использовать Promise в коде на всех - и, until all browsers support native promises, я советовал бы против него, если вы не загружаете свою собственную библиотеку обещание.

Но главная причина заключается в том, что jQuery реализует обещания в достаточной степени для этой задачи. Каждая функция jQuery Ajax возвращает обещание, вы можете использовать их напрямую.

Вот как я бы написать свой код:

function connect($row) { 
    var columns = $row.children("td"); 
    $(columns[6]).html("<span class='spinner'><i class='fa fa-spinner fa-spin'></i></span>"); 

    return $.getJSON("functions/connect_with.php", { 
     employee_id: $row.attr("rel"), 
     trees: $("#selectedTree").val() 
    }).done(function (response) { 
     $(columns[1]).text(response.message.person.email); 
     if(response.success) { 
      $(columns[2]).text(response.message.person.name.givenName); 
      $(columns[3]).text(response.message.person.name.familyName); 
      $(columns[4]).text(response.message.person.employment.title); 
     } 
     $(columns[5]).html("<i class='text-success fa fa-sitemap'></i>"); 
    }).always(function() { 
     $(columns[6]).html("<i class='text-success fa fa-check'></i>"); 
    }); 
} 


$("#connectAll").click(function() { 
    $(this).hide(); 

    var calls = $(".staffMember input:checked").map(function() { 
     return connect($(this).parents("tr")); 
    }).toArray(); 

    $.when.apply($, calls) 
    .fail(function (jqXhr, status, error) { 
     // display or handle the error 
    }) 
    .always(function() { 
     $("#connectAll").show(); 
    }); 
}); 

Боковых ноты:

  • Вы должны реализовать обработчик ошибок (.fail(...))
  • кода, который удаляет блесну или восстанавливающие кнопки должны сидеть в обработчике .always(), так что функциональность страницы не теряется из-за прерывистой ошибки Ajax.
  • Для установки текстовых значений вы должны использовать .text() jQuery (в отличие от .html()).
2

Вместо того, чтобы вызывать apply использование Promise.all

Это выполняет множество обещаний и возвращает сразу все закончили.

Так что ваш код станет:

$("#connectAll").click(function() { 
    alert("OFF WE GO"); 
    $(this).hide(); 
    var methods = []; 
    $(".staffMember input:checked").each(function(index, checkbox) { 
    checkbox = $(checkbox); 
    var row = checkbox.parents("tr"); 
    methods.push(connect(row)); 
    }); 
    Promise.all(methods).then(values => { 
    alert("WE DID IT MOM"); 
    $("#connectAll").show(); 
    }).catch(reason => { 
    alert("MOM, SOMETHING WENT WRONG"); 
    }); 
}); 
+0

В контексте jQuery гораздо лучше рекомендовать '$ .when' над' Promise.all'. Он работает одинаково (за исключением того, что вам нужно '.apply()', потому что он ожидает список параметров, а не массив), но он также работает в браузерах, у которых нет поддержки на основе обещаний. – Tomalak

+0

Тогда что бы я вернулся в методе 'connect'? Отложенный объект или ...? @Tomalak – ThePerplexedOne

+0

Вы должны вернуть результат вызова Ajax ('return $ .getJSON (...) ') - это уже обещания в jQuery, вам вообще не нужен вызов' new Promise() '. – Tomalak

Смежные вопросы