簡體   English   中英

如何在JavaScript中正確使用Promise.then()?

[英]How to correctly use Promise.then() in JavaScript?

我試圖使用Promises一個接一個地運行某些功能,但是不知何故第二個功能要么在第一個功能之前執行,要么根本不執行。 情況是這樣的:

我具有以下功能:

  • 從局部文件夾中加載可重復使用的html代碼的代碼:
    function insertingPartials() {
        return new Promise( function(resolve,reject) {
            $('#navbar-placeholder').load('/Assets/Partials/navbar.html');
            $('#jumbotron-placeholder').load('/Assets/Partials/jumbotron.html');
            $('#footer-placeholder').load('/Assets/Partials/footer.html');

            resolve();
            reject('Error');
        });
  • 進行語言調整的一種
function languageSpecifics() {
    return new Promise( function(resolve,reject) {
        //showing correct text per html language
        $('span[lang=' + $('html')[0].lang + ']').show();
        $('div[lang=' + $('html')[0].lang + ']').show();
        //disabling the current language from the language selection menu
        $('a[lang=' + $('html')[0].lang + ']').addClass('disabled');
        //links dynamically point to the correct sub-pages
        $('.blog-link').attr('href', '/' + $('html')[0].lang + '/Blog/');
        $('.prod-link').attr('href', '/' + $('html')[0].lang + '/' + $('.prod-link span[lang=' + $('html')[0].lang + ']').text() + '/');
        $('#en').attr('href', window.location.href.replace($('html')[0].lang, 'en'));
        $('#es').attr('href', window.location.href.replace($('html')[0].lang, 'es'));
        $('#ro').attr('href', window.location.href.replace($('html')[0].lang, 'ro'));

        resolve();
        reject('Error in ' + arguments.callee.name);
    });
}
  • 將內容滑入視圖的一種:
function loadContent() {
    return new Promise( function(resolve,reject) {
        //fading content in
        $('nav').animate({top: '0'});
        $('footer').animate({bottom: '0'});
        $('.main-content').animate({right: '0'}).css('overflow', 'auto');
        //fading preloading out
        $('.spinner-border').fadeOut();
        $('#preloading').removeClass('d-flex').addClass('d-none');

        resolve();
        reject('Error in ' + arguments.callee.name);
    });
}
  • 和一個可以調節容器高度的容器
function setContainerHeight() {
    //setting the height of the container
    $('.container').css('height', $('body').height() - ($('nav').height() + $('footer').height()) + 'px');
}

我想做的是讓功能按我在上面放置的順序執行。 以下代碼輸出1,2,3,4,但功能“ languageSpecifics”未執行或在“ inserttingPartials”之前執行,因為已加載了局部文件,然后組件滑入了視圖,但是看不到文本,並且鏈接指向任何地方。

$(document).ready( function() {

    console.log('1')
    insertingPartials().then( function() {
        console.log('2');
        languageSpecifics().then( function() {
            console.log('3');
            loadContent().then( function() {
                console.log('4');
                setContainerHeight();
            });
        });
    });

});

如果我在瀏覽器控制台中分別執行這些功能,則會得到所需的輸出,並且每個諾言都將兌現。 如果我使用.then()運行它們,則promise將返回待定狀態,並且頁面上不會顯示任何文本。 (兩個嵌套的“ .then(.then())和同一級別的“ .then()。then()”都給出相同的結果)

我想知道我在做什么錯。 另外,如果有更好/更有效的方法來實現我在此處嘗試執行的操作,請告知。

無法發表評論。 Afaik .load()是一個異步函數,這意味着在加載頁面之前調用以下解析。 您應該嘗試使用.load()的回調參數,並且僅在所有參數都完成后才調用resolve。

如果您想要同步行為(即依次啟動一個函數),請嘗試使用async function和await關鍵字。

  • 將每個函數包裝在Promise中,包括一個以ms或s為單位的時間數字:

     const _A_ = () => { return new Promise(resolve => { setTimeout(() => resolve({{FUNCTION}}), {{TIME}}); }); } 
  • async函數包裝在所有Promise中:

     const _Y_ = async() => { ... /* Promises */ } 
  • async函數的末尾,使用關鍵字await依次調用每個Promise:

     const _Y_ = async() => { ... /* Promises */ await _A_(); await _B_(); await _C_(); await _D_(); } 

以下演示不起作用,如果您要查看功能演示,請轉到此Plunker

 const main = document.forms[0]; const loader = async(time = 700) => { const ajax1 = () => { return new Promise(resolve => { setTimeout(() => resolve($('.base ol').append($('<li>').load('comp.html #set1'))), time); }); } const ajax2 = () => { return new Promise(resolve => { setTimeout(() => resolve($('.base ol').append($('<li>').load('comp.html #set2'))), time); }); } const ajax3 = () => { return new Promise(resolve => { setTimeout(() => resolve($('.base ol').append($('<li>').load('comp.html #set3'))), time); }); } const ajax4 = () => { return new Promise(resolve => { setTimeout(() => resolve($('.base ol').append($('<li>').load('comp.html #set4'))), time); }); } await ajax1(); await ajax2(); await ajax3(); await ajax4(); } const getComp = e => { e.preventDefault(); loader(); } main.onsubmit = getComp; 
 .set::before { content: attr(id); font: 400 16px/1 Consolas; } button { font: inherit; float: right; } 
 <!doctype html> <html> <head> </head> <body> <form id='main'> <fieldset class='base'> <legend>Synchronous AJAX</legend> <ol></ol> </fieldset> <button>GO</button> </form> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> </body> </html> 

load()是異步的,並且允許完整的回調,但不能保證

您可以將load()替換為$.get() ,它確實返回promise,並在所有三個加載完成后使用$.when()進行調用:

除了ajax之外,沒有什么異步的東西需要在dom操作函數中使用promise,並且您可以按首選順序調用這些函數而無需任何promise ....僅初始加載promise

就像是:

// page load call
$(function(){
   loadAllPartials().then(function(){
      languageSpecifics();
      contentDisplay();   
   });
});

// get single partial and insert in dom, return promise
function loadPartial(url, selector) {
  return $.get(url).then(function(data) {
    $(selector).html(data);
  })
}

// return `$.when()` promise for loading all partials
function loadAllPartials() {
  return $.when(
    loadPartial('/Assets/Partials/navbar.html', '#navbar-placeholder'),
    loadPartial('/Assets/Partials/jumbotron.html', '#jumbotron-placeholder'),
    loadPartial('/Assets/Partials/footer.html', '#footer-placeholder')
  )
}

// adjusted to synchronous code, no promises needed
function contentDisplay() {

  //fading content in
  $('nav').animate({top: '0'});
  $('footer').animate({bottom: '0'});
  $('.main-content').animate({right: '0'}).css('overflow', 'auto');
  //fading preloading out
  $('.spinner-border').fadeOut();
  $('#preloading').removeClass('d-flex').addClass('d-none');

}

function languageSpecifics() {
  // store lang value once instead of searching dom each time
  var lang = $('html')[0].lang
  //showing correct text per html language
  $('span[lang=' + lang + ']').show();
  $('div[lang=' + lang + ']').show();
  //disabling the current language from the language selection menu
  $('a[lang=' + lang + ']').addClass('disabled');
  //links dynamically point to the correct sub-pages
  $('.blog-link').attr('href', '/' + lang + '/Blog/');
  $('.prod-link').attr('href', '/' + lang + '/' + $('.prod-link span[lang=' + lang + ']').text() + '/');
  $('#en').attr('href', window.location.href.replace(lang, 'en'));
  $('#es').attr('href', window.location.href.replace(lang, 'es'));
  $('#ro').attr('href', window.location.href.replace(lang, 'ro'));


}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM