2016-03-14 3 views
4

В Угловое, следующие фрагменты кажутся эквивалентными:

let deferred = $q.defer(); 
if(whatever) { 
    deferred.resolve('something'); 
} 
else { 
    deferred.reject('nah'); 
} 
return deferred.promise; 

и

return $q((resolve,reject) => { 
    if(whatever) { 
     resolve('something'); 
    } 
    else { 
     reject('nah'); 
    } 
}); 

Мой вопрос: если они не являются эквивалент, как они отличаются? Если они эквивалентны, есть ли веская причина для предпочтения одного над другим?

+0

https://docs.angularjs.org/api/ng/service/$q Цель отложенного объекта заключается в том, чтобы выставить связанный экземпляр Promise, а также API, которые могут использоваться для сигнализации успешного или неудачного завершения, а также статуса задачи. – Noctisdark

ответ

5

Вторая версия, которую вы отправили, является той, которая следует за Promise/A+-Спецификация.

С функциональной точки зрения обе версии являются эквивалентными. Первая версия (на мой взгляд) упрощает чтение асинхронного кода как синхронного, но вторая использует синтаксис, который сделал его в ES2015, а также будет частью ES6, то есть следующих версий javascript.

Таким образом, выбор зависит от вас, но вы можете ожидать увидеть гораздо больше второго типа синтаксиса обещаний в будущем.

+0

Нет, Promise/A + не указывает, как строятся обещания. Можно использовать как отсрочки, так и конструкторы с исполнителями. – Bergi

3

Что касается $q, то обещания идут, в сравнении с другими нет большой поведенческой разницы. Основное преимущество второго подхода заключается в том, что он использует тот же стиль, что и нативные обещания, и он прекрасно содержит логику для решения обещания вместо того, чтобы иметь свободную отложенную завивку (это, вероятно, является одной из причин, по которым национальные обещания шли с последний style).

Я ошибочно сказал, что второй подход поймает синхронные ошибки в переданной функции и преобразует их в отклоненное обещание. Это верно для местных обещаний, обещаний Q, обещаний Bluebird и, возможно, других, но это неверно для $q(). $q просто обработает ошибку как неперехваченную ошибку и зарегистрирует ее на консоли.

Вот пример, используя обещания Bluebird, о том, что я описывал. Это отличный повод, чтобы использовать последний стиль, если вы используете другие обещания, чем $q:

function queryValue(callback) { 
 
    throw new Error("Not implemented yet!!!"); 
 
} 
 

 
function makeConstructorPromise() { 
 
    return new Promise(function(resolve) { 
 
    queryValue(function(value) { 
 
     resolve(value); 
 
    }); 
 
    }); 
 
} 
 

 
function makeDeferredPromise() { 
 
    let deferred = Promise.defer(); 
 

 
    queryValue(function(value) { 
 
    deferred.resolve(value); 
 
    }); 
 

 
    return deferred.promise; 
 
} 
 

 
makeConstructorPromise() 
 
    .catch(function(error) { 
 
    console.error('caught the constructed promise error!', error); 
 
    }); 
 

 
makeDeferredPromise() 
 
    .catch(function(error) { 
 
    // not caught 
 
    console.error('caught the deferred promise error!', error); 
 
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.5.1/bluebird.min.js"></script>

Отложенный подход старомоден и может иметь практическое применение в конкретных случаях, но 99 % времени, подход конструктора - путь.

Это безопаснее (в большинстве обещаний) и согласуется с тем, как работает ES6.

+0

странно, документы говорят об обратном: https://docs.angularjs.org/api/ng/service/$q - «Примечание: в отличие от поведения ES6 исключение, созданное в функции конструктора, НЕ Явным образом отвергает обещание». – Marnes

+0

@ Марнес Йэйкс, ты прав. Думаю, я только что предположил, что функция '$ q' работает как конструктор Promise от ES6, Bluebird и Q, но это не так. Я исправлю свой ответ через несколько часов. – JLRishe

+0

Эй, чувак, не забудь изменить свой ответ, как ты сказал. – Marnes

0

Функциональность эквивалентна - ее больше о «стиле».

Один синтаксис больше похож на Kris Kowals Q, который был одним из первых реализаций обещаний в javascript.

Другой синтаксис больше похож на реализацию, которую мы будем получать с ES6.

Так что используйте, с чем вам более комфортно - если вы начнете учиться, я предлагаю использовать путь ES6, потому что это будет будущее «стандартного javascript», а не только угловатое.

Больше информации об этой теме и ваш вопрос, вы можете найти непосредственно в Angualar доку: https://docs.angularjs.org/api/ng/service/ $ д/

Смежные вопросы