Перед 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
.
Попробуйте сделать следующее:
class Foo {
function bar() {
$static = !(isset($this) && get_class($this) == __CLASS__);
}
}
Источник: seancoates.com через Google
«Выкопать его из debug_backtrace ()» не так уж много работы. У debug_backtrace () есть член 'type', который является '::', если вызов статический, и '->', если это не так. Итак:
class MyClass {
public function doStuff() {
if (self::_isStatic()) {
// Do it in static context
} else {
// Do it in object context
}
}
// This method needs to be declared static because it may be called
// in static context.
private static function _isStatic() {
$backtrace = debug_backtrace();
// The 0th call is to _isStatic(), so we need to check the next
// call down the stack.
return $backtrace[1]['type'] == '::';
}
}
Проверка того, установлено ли $this
, не всегда будет работать.
Если вы вызываете статический метод изнутри объекта, тогда $this
будет установлен как контекст вызывающего. Если вы действительно хотите получить информацию, я думаю, вам придется выкопать ее из debug_backtrace
. Но зачем вам это вообще нужно? Скорее всего, вы могли бы изменить структуру своего кода таким образом, чтобы вы этого не сделали.
Тест для $this
:
class Foo {
function bar() {
if (isset($this)) {
echo "Y";
} else {
echo "N";
}
}
}
$f = new Foo();
$f->bar(); // prints "Y"
Foo::bar(); // prints "N"
Редактировать: Как указывает pygorex1, вы также можете принудительно метод, который будет оцениваться статически:
class Foo {
static function bar() {
if (isset($this)) {
echo "Y";
} else {
echo "N";
}
}
}
$f = new Foo();
$f->bar(); // prints "N", not "Y"!
Foo::bar(); // prints "N"
Я фактически использую эту строку кода во всех моих сценариях, она работает хорошо и предотвращает ошибки.
class B{
private $a=1;
private static $static=2;
function semi_static_function(){//remember,don't declare it static
if(isset($this) && $this instanceof B)
return $this->a;
else
return self::$static;
}
}
Использование instanceof не является паранойей:
Если класс A вызывает класс B, статическая функция $this
может существовать в области A; Я знаю, что это довольно запутано, но php делает это.
instanceof
исправит это и позволит избежать конфликтов с классами, которые могут реализовывать ваши «полустатические» функции.
Это старый вопрос, но я добавлю альтернативный ответ.
Существует два магических метода
__call($name, $arguments)
запускается при вызове недоступных методов в контексте объекта.
__callStatic($name, $arguments)
срабатывает при вызове недоступных методов в статическом контексте.
<?php
class MethodTest
{
public function __call($name, $arguments)
{
// Note: value of $name is case sensitive.
echo "Calling object method '$name' "
. implode(', ', $arguments). "\n";
}
/** As of PHP 5.3.0 */
public static function __callStatic($name, $arguments)
{
// Note: value of $name is case sensitive.
echo "Calling static method '$name' "
. implode(', ', $arguments). "\n";
}
}
$obj = new MethodTest;
$obj->runTest('in object context');
MethodTest::runTest('in static context'); // As of PHP 5.3.0
Выходы
Вызов метода объекта 'runTest' в контексте объекта
Вызов статического метода 'runTest' в статическом контексте
<?
class A {
function test() {
echo isset($this)?'not static':'static'; }
}
$a = new A();
$a->test();
A::test();
?>
Редактировать: избили его.
Просто верните класс как новый внутри функции.
return new self();
Тестирование isset ($ this) не работало для меня, как упомянул troelskn «$ this будет установлен как контекст вызывающего абонента».
abstract class parent
{
function bar()
{
if( isset( $this ) ) do_something();
else static::static_bar();
}
function static static_bar()
{
do_something_in_static_context();
}
}
class child extends parent
{
...
}
$foo = new child();
$foo->bar(); //results in do_something()
child::bar(); //also results in do_something()
В моем случае у меня есть родительский класс с объектом и статической контекстной функцией, которая выполняет ту же задачу в дочернем классе. isset ($ this) всегда возвращал true, однако я заметил, что хотя $ this переключается между классом child в объектном контексте и вызовом (?) класса в статическом контексте, чудесная магическая константа __class__
осталась родительской для класса!
Вскоре после нахождения функции is_a мы можем проверить, находимся ли мы в статическом контексте:
if( is_a($this, __CLASS__) ) ...
Возвращает true в контексте объекта, false в статическом контексте.
Пожалуйста, протестируйте свои собственные реализации, так как я проверяю это только для моего конкретного сценария (уникальный случай вызова наследования) в 5.3.
К сожалению (для моего случая) я пока не могу найти способ вызвать static_bar()
, так как $ this и static относятся к отдельному классу, а __class__
относится к родительскому классу. Мне нужен способ вызова child :: static_bar () ...