我已經簡化了這個問題。我有 3 個函式,我想在每個函式之間運行 2 秒延遲。以下代碼正在作業:
$.when(one()).done(function () {
$.when(delay(2000)).done(function () {
$.when(two()).done(function () {
$.when(delay(2000)).done(function () {
$.when(three()).done(function () {
console.log('finished');
});
});
});
});
});
function delay(ms) {
var waitForDelay = new $.Deferred();
setTimeout(function () {
waitForDelay.resolve().promise();
}, ms);
return waitForDelay.promise();
}
function one() {
console.log('one');
return new $.Deferred().resolve().promise();
}
function two() {
console.log('two');
return new $.Deferred().resolve().promise();
}
function three() {
console.log('three');
return new $.Deferred().resolve().promise();
}
但是,當我嘗試重構它時,它不再等待延遲的時間:
one().done(delay(2000)).done(two).done(delay(2000)).done(three).done(function () {
console.log('finished');
});
我如何重構以鏈接這些承諾而不是嵌套它們?我想使用 jQuery 來實作舊版瀏覽器的兼容性。
uj5u.com熱心網友回復:
我的建議是根本不要使用 jQuery 奇怪的類似Promise 的資料結構。
讓您的函式回傳一個實際的Promise(顯式地或通過使它們成為異步函式)和await鏈中的每個步驟。
const delay = (ms) => new Promise((res) => setTimeout(res, ms));
// an async function implicitly returns a promise
const one = async () => {
console.log("one");
}
// or you can return one manually
const two = () => {
console.log("two");
return Promise.resolve();
}
const three = async () => {
console.log("three");
}
// await each step in an async function (an async IIFE in this case)
(async () => {
await one();
await delay(2000);
await two();
await delay(2000);
await three();
console.log("finished");
})();
.then()如果您喜歡這種風格,也可以使用
// Convenience function so you don't repeat yourself
const waitTwoSeconds = () => delay(2000);
one()
.then(waitTwoSeconds)
.then(two)
.then(waitTwoSeconds)
.then(three)
.then(() => {
console.log("finished");
});
如果你必須使用 jQuery,它看起來并沒有太大的不同
function delay(ms) {
var d = $.Deferred();
setTimeout(d.resolve, ms);
return d.promise();
}
function one() {
console.log("one");
return $.Deferred().resolve().promise();
}
function two() {
console.log("two");
return $.Deferred().resolve().promise();
}
function three() {
console.log("three");
return $.Deferred().resolve().promise();
}
function waitTwoSeconds() {
return delay(2000);
}
one()
.then(waitTwoSeconds)
.then(two)
.then(waitTwoSeconds)
.then(three)
.then(function() {
console.log("finished");
});
<!-- Note jQuery 1.8 was the first to have chainable deferreds -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
我使用.then()而不是.done()因為后者不鏈接并且在可用時使用$.when()是不必要.then()的。
uj5u.com熱心網友回復:
從 Phil 的回答中汲取靈感,這里有一個與舊瀏覽器兼容的解決方案。
首先,將delay()函式更改為回傳函式:
function delay(ms) {
return function() {
var waitForDelay = new $.Deferred();
setTimeout(function () {
waitForDelay.resolve().promise();
}, ms);
return waitForDelay.promise();
}
}
所有其他功能與問題中的相同。
最后將.done()s替換為.then()s 以使它們成為鏈式:
one().then(delay(2000)).then(two).then(delay(2000)).then(three).then(function () {
console.log('finished');
});
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/494002.html
標籤:javascript jQuery
上一篇:當我在地圖功能中執行onclick時,它適用于所有這些
下一篇:如何擺脫for回圈
