我试图使用Promises一个接一个地运行某些功能,但是不知何故第二个功能要么在第一个功能之前执行,要么根本不执行。 情况是这样的:
我具有以下功能:
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()”都给出相同的结果)
我想知道我在这里做错了什么。 另外,如果有更好/更有效的方法来实现我在此处尝试执行的操作,请提出建议。
答案 0 :(得分:2)
还不能发表评论。 Afaik .load()是一个异步函数,这意味着在加载页面之前调用以下解析。您应该尝试使用.load()的回调参数,并且仅在所有参数都完成后才调用resolve。
答案 1 :(得分:1)
如果您想要同步行为(即依次执行一个功能,请尝试使用async
函数和await
关键字。
在Promise中包装每个函数,包括一个以ms或s为单位的时间数字:
const _A_ = () => { return new Promise(resolve => { setTimeout(() => resolve({{FUNCTION}}), {{TIME}}); }); }
在所有Promise中包装一个async
函数:
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>
答案 2 :(得分:1)
load()
是异步的,它允许完整的回调,但不能保证诺言
您可以将load()
替换为$.get()
,它确实会返回承诺并在所有3个加载完成后使用$.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'));
}