Если вы используете yml и Twig для переводов в Symfony и хотите использовать многострочные переводы в Javascript, возврат каретки добавляется сразу после перевода. Таким образом, даже следующий код:
var javascriptVariable = "{{- 'key'|trans -}}";
Который имеет следующий перевод yml:
key: >
This is a
multi line
translation.
По-прежнему будет выглядеть следующий код в html:
var javascriptVariable = "This is a multi line translation.
";
Итак, знак минус в Twig не решает этого. Решение состоит в том, чтобы добавить этот знак минуса после знака в yml:
key: >-
This is a
multi line
translation.
Будет иметь правильный результат, многострочный перевод на одной строке в Twig:
var javascriptVariable = "This is a multi line translation.";
Перед ES2017 и async/await
(см. ниже для опции в ES2017), вы не можете использовать .forEach()
, если хотите дождаться обещания, потому что обещания не блокируются. Javascript и обещания просто не работают.
async
или Bluebird
, которая будет их упорядочивать для вас. Существует множество различных альтернатив , но .forEach()
не сделает этого для вас.
Вот пример последовательности, использующей цепочку обещаний с угловыми обещаниями (если objects
- массив):
objects.reduce(function(p, val) {
return p.then(function() {
return doSomething(val);
});
}, $q.when(true)).then(function(finalResult) {
// done here
}, function(err) {
// error here
});
И, используя стандартные обещания ES6, это будет:
objects.reduce(function(p, val) {
return p.then(function() {
return doSomething(val);
});
}, Promise.resolve()).then(function(finalResult) {
// done here
}, function(err) {
// error here
});
Вот пример ручного секвенирования (если objects
- массив), хотя это не сообщает завершение или ошибки, подобные описанному выше:
function run(objects) {
var cntr = 0;
function next() {
if (cntr < objects.length) {
doSomething(objects[cntr++]).then(next);
}
}
next();
}
ES2017
В ES2017 функция async/wait
позволяет вам «ждать» обещания выполнить перед продолжением итерации цикла при использовании не-функциональных циклов, таких как for
или while
:
Код должен содержаться внутри функции async
, а затем вы можете использовать await
, чтобы сообщить интерпретатору подождать, пока обещание будет разрешено до продолжения цикла. Обратите внимание, что, хотя это похоже на поведение типа «блокировка», оно не блокирует цикл события. Другие события в цикле событий все еще могут обрабатываться во время await
.
Да, вы можете использовать angular.forEach
для достижения этого.
Вот пример (если objects
- массив):
// Define the initial promise
var sequence = $q.defer();
sequence.resolve();
sequence = sequence.promise;
angular.forEach(objects, function(val,key){
sequence = sequence.then(function() {
return doSomething(val);
});
});
как это можно сделать, используя array.reduce
, как и ответ @ friend00 (если objects
- массив):
objects.reduce(function(p, val) {
// The initial promise object
if(p.then === undefined) {
p.resolve();
p = p.promise;
}
return p.then(function() {
return doSomething(val);
});
}, $q.defer());
проверить $ q на угловом:
function outerFunction() {
var defer = $q.defer();
var promises = [];
function lastTask(){
writeSome('finish').then( function(){
defer.resolve();
});
}
angular.forEach( $scope.testArray, function(value){
promises.push(writeSome(value));
});
$q.all(promises).then(lastTask);
return defer;
}
q.all()
, чтобы знать, когда все будет сделано. Я, хотя ОП спросил, как последовательно выполнять операции по одному.
– jfriend00
11 March 2015 в 11:10
Это может помочь кому-то, если я попробовал несколько вышеперечисленных решений, прежде чем придумать свой собственный, который действительно работал для меня (другие не сделали этого)
var sequence;
objects.forEach(function(item) {
if(sequence === undefined){
sequence = doSomethingThatReturnsAPromise(item)
}else{
sequence = sequence.then(function(){
return doSomethingThatReturnsAPromise(item)
});
}
});
Самый простой способ - создать функцию и вручную перебрать все объекты в массиве после каждого обещания.
var delayedFORLoop = function (array) {
var defer = $q.defer();
var loop = function (count) {
var item = array[count];
// Example of a promise to wait for
myService.DoCalculation(item).then(function (response) {
}).finally(function () {
// Resolve or continue with loop
if (count === array.length) {
defer.resolve();
} else {
loop(++count);
}
});
}
loop(0); // Start loop
return defer.promise;
}
// To use:
delayedFORLoop(array).then(function(response) {
// Do something
});
Пример также доступен на моем GitHub: https: //github.com/pietervw/Deferred-Angular-FOR-Loop-Example
Это сработало для меня так. Я не знаю, подходит ли это подход, но может помочь уменьшить линии
function myFun(){
var deffer = $q.defer();
angular.forEach(array,function(a,i) {
Service.method(a.id).then(function(res) {
console.log(res);
if(i == array.length-1) {
deffer.resolve(res);
}
});
});
return deffer.promise;
}
myFun().then(function(res){
//res here
});
$q.defer().resolve()
разрешает обещание, но возвращает неопределенный, поэтомуp
не определено для первого элемента. – AgDude 1 December 2015 в 20:03$q.dever().resolve()
не работало для меня (Угловое 1.4.3),p
былоundefined
при первом вызове. Но это сработало:$q(function(resolve) { resolve();})
– artkoenig 12 March 2016 в 16:21.resolve()
возвращает обещание. Возможно, это было добавлено после 1.4.3? В любом случае, ваш метод работает отлично. Кроме того, он должен быть$q.defer().resolve()
- вы пишете его по-разному в своем комментарии. Я думаю, вы также можете использовать$q.when(true)
. – jfriend00 12 March 2016 в 17:15