Czekać na wszystkie obietnice do rozwiązania
Więc mam sytuację, w której mam wiele łańcuchów obietnic o nieznanej długości. Chcę wykonać jakąś akcję, gdy wszystkie łańcuchy zostaną przetworzone. Czy to w ogóle możliwe? Oto przykład:
app.controller('MainCtrl', function($scope, $q, $timeout) {
var one = $q.defer();
var two = $q.defer();
var three = $q.defer();
var all = $q.all([one.promise, two.promise, three.promise]);
all.then(allSuccess);
function success(data) {
console.log(data);
return data + "Chained";
}
function allSuccess(){
console.log("ALL PROMISES RESOLVED")
}
one.promise.then(success).then(success);
two.promise.then(success);
three.promise.then(success).then(success).then(success);
$timeout(function () {
one.resolve("one done");
}, Math.random() * 1000);
$timeout(function () {
two.resolve("two done");
}, Math.random() * 1000);
$timeout(function () {
three.resolve("three done");
}, Math.random() * 1000);
});
W tym przykładzie ustawiłem $q.all()
dla obietnic 1, 2 i 3, które zostaną rozwiązane w jakimś losowym czasie. Następnie dodaję obietnice na końcu 1 i 3. Chcę, aby all
rozwiązał się, gdy wszystkie łańcuchy zostaną rozwiązane. Oto wyjście, gdy uruchamiam to kod:
one done
one doneChained
two done
three done
ALL PROMISES RESOLVED
three doneChained
three doneChainedChained
Czy jest sposób, aby poczekać, aż łańcuchy się rozwiążą?
5 answers
Chcę, aby wszystko zostało rozwiązane, gdy wszystkie łańcuchy zostaną rozwiązane.
Jasne, więc po prostu przekaż obietnicę każdego łańcucha do all()
zamiast początkowych obietnic:
$q.all([one.promise, two.promise, three.promise]).then(function() {
console.log("ALL INITIAL PROMISES RESOLVED");
});
var onechain = one.promise.then(success).then(success),
twochain = two.promise.then(success),
threechain = three.promise.then(success).then(success).then(success);
$q.all([onechain, twochain, threechain]).then(function() {
console.log("ALL PROMISES RESOLVED");
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-04 16:24:31
Zaakceptowana odpowiedź jest prawidłowa. Chciałbym podać przykład, aby rozwinąć go nieco dla tych, którzy nie są zaznajomieni z promise
.
Przykład:
W moim przykładzie muszę zastąpić src
atrybuty znaczników img
różnymi lustrzanymi adresami URL, jeśli są dostępne przed renderowaniem zawartości.
var img_tags = content.querySelectorAll('img');
function checkMirrorAvailability(url) {
// blah blah
return promise;
}
function changeSrc(success, y, response) {
if (success === true) {
img_tags[y].setAttribute('src', response.mirror_url);
}
else {
console.log('No mirrors for: ' + img_tags[y].getAttribute('src'));
}
}
var promise_array = [];
for (var y = 0; y < img_tags.length; y++) {
var img_src = img_tags[y].getAttribute('src');
promise_array.push(
checkMirrorAvailability(img_src)
.then(
// a callback function only accept ONE argument.
// Here, we use `.bind` to pass additional arguments to the
// callback function (changeSrc).
// successCallback
changeSrc.bind(null, true, y),
// errorCallback
changeSrc.bind(null, false, y)
)
);
}
$q.all(promise_array)
.then(
function() {
console.log('all promises have returned with either success or failure!');
render(content);
}
// We don't need an errorCallback function here, because above we handled
// all errors.
);
Explanation:
From AngularJS docs :
Metoda then
:
Then (successCallback, errorCallback, notifyCallback) - niezależnie od tego, kiedy obietnica została lub zostanie rozwiązana lub odrzucona, następnie wywołuje jeden z zakończonych sukcesem lub błędem wywołań zwrotnych asynchronicznie, gdy tylko wynik jest dostępny. Wywołania są wywoływane przez pojedynczy argument: wynik lub powód odrzucenia.
$q. all (promises)
Łączy wiele obietnic w jedną obietnicę, która jest rozwiązywana, gdy wszystkie obietnice wejściowe są rozwiązane.
The promises
param może być szeregiem obietnic.
O bind()
, Więcej informacji tutaj: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:14
Ostatnio miałem ten problem, ale z niewiadomą liczbą obietnic.Rozwiązane przy użyciu jQuery.map () .
function methodThatChainsPromises(args) {
//var args = [
// 'myArg1',
// 'myArg2',
// 'myArg3',
//];
var deferred = $q.defer();
var chain = args.map(methodThatTakeArgAndReturnsPromise);
$q.all(chain)
.then(function () {
$log.debug('All promises have been resolved.');
deferred.resolve();
})
.catch(function () {
$log.debug('One or more promises failed.');
deferred.reject();
});
return deferred.promise;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-18 10:46:13
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-13 16:12:43
Możesz użyć " wait "w"funkcji asynchronicznej" .
app.controller('MainCtrl', async function($scope, $q, $timeout) {
...
var all = await $q.all([one.promise, two.promise, three.promise]);
...
}
Uwaga: nie jestem w 100% pewien, że można wywołać funkcję asynchroniczną z funkcji nie-asynchronicznej i mieć odpowiednie wyniki.
To powiedziało, że to nigdy nie będzie używane na stronie internetowej. Ale do testowania obciążenia/testu integracji...może.
Przykładowy kod:
async function waitForIt(printMe) {
console.log(printMe);
console.log("..."+await req());
console.log("Legendary!")
}
function req() {
var promise = new Promise(resolve => {
setTimeout(() => {
resolve("DARY!");
}, 2000);
});
return promise;
}
waitForIt("Legen-Wait For It");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-28 17:22:19