Как я могу сказать, является ли объект обещанием?



будь то обещание ES6 или обещание bluebird, обещание Q и т. д.



Как проверить, является ли данный объект обещанием?

438   13  

13 ответов:

как библиотека обещаний решает

если у него есть - Это только использование стандартных библиотек обещаний.

спецификация Promises/A+ имеет понятие под названием then способный, который в основном " объект с then метод". Обещания будут и должны ассимилироваться что-нибудь С помощью метода then. Все обещания реализации вы упомянули сделать это.

если мы посмотрим на спецификация:

2.3.3.3 если then это функция, вызовите ее с x как это, первый аргумент resolvePromise, а второй аргумент rejectPromise

это также объясняет обоснование этого проектного решения:

это лечение thenables позволяет реализации promise взаимодействовать, если они предоставляют Promises / A+-compliant then метод. Он также позволяет обещания / a+ реализации "ассимилировать" несоответствующие реализации с разумными тогда методами.

как вы должны решить

вы не должны-вместо этого позвоните Promise.resolve(x) (Q(x) в Q), что составит всегда преобразование любого значения или внешнего then способный в доверенное обещание. Это безопаснее и проще, чем выполнять эти проверки самостоятельно.

действительно нужно быть уверенным?

вы всегда можете запустить его через тест люкс: D

проверка, если что-то обещаю, излишне усложняет код, просто используйте Promise.resolve

Promise.resolve(valueOrPromiseItDoesntMatter).then(function(value) {

})

вот мой оригинальный ответ, который был ратифицировано в спецификации как способ проверить обещание:

Promise.resolve(obj) == obj

это работает, потому что алгоритм явно требует, чтобы Promise.resolve должен вернуть точный объект, переданный в if и только если это обещание по определению спецификаций.

у меня есть еще один ответ, который использовали, чтобы сказать это, но я изменил его на что-то другое, когда он не работал с сафари в то время. Это было год назад, и теперь она надежно работает даже в сафари.

Я бы отредактировал свой оригинальный ответ, но это было неправильно, учитывая, что к настоящему времени больше людей проголосовали за измененное решение в этом ответе, чем за оригинал. Я считаю, что это лучший ответ, и я надеюсь, что вы согласны.

обновление: это уже не лучший ответ. Пожалуйста, проголосуйте мой другой ответ.

obj instanceof Promise

должны сделать это. Обратите внимание, что это может надежно работать только с собственными обещаниями es6.

Если вы используете прокладку, библиотеку обещаний или что-то еще, претендующее на обещание, тогда может быть более уместно проверить "thenable" (что-нибудь с .then метод), как показано в другие ответы здесь.

if (typeof thing.then === 'function') {
    // probably a promise
} else {
    // definitely not a promise
}

чтобы увидеть, является ли данный объект native ES6 Promise, мы можем использовать этот предикат:

function isPromise(value) {
  return value && Object.prototype.toString.call(value) === "[object Promise]";
}

Call ing toString непосредственно с Object.prototype возвращает a родной строковое представление для данного типа объекта, который составляет "[object Promise]" в нашем случае. Это гарантирует, что данный объект

  • обходит ложные срабатывания, такие как..:
    • самоопределяющийся тип объекта с тем же именем конструктора ("Обещать.)"
    • самописных toString метод данного объекта.
  • работает в нескольких контекстах среды (например, iframes) в отличие от instanceof или isPrototypeOf.

вот код формы https://github.com/ssnau/xkit/blob/master/util/is-promise.js

!!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';

если объект с then метод, он должен рассматриваться как Promise.

в случае, если вы используете Typescript, Я хотел бы добавить, что вы можете использовать функцию "виды сказуемого". Просто следует обернуть логическую проверку в функцию, которая возвращает x is Promise<any> и вам не нужно будет делать приведения типов. Ниже на моем примере, c это либо обещание, либо один из моих типов, которые я хочу преобразовать в обещание, вызвав c.fetch() метод.

export function toPromise(c: Container<any> | Promise<any>): Promise<any> {
    if (c == null) return Promise.resolve();
    return isContainer(c) ? c.fetch() : c;
}

export function isContainer(val: Container<any> | Promise<any>): val is Container<any> {
    return val && (<Container<any>>val).fetch !== undefined;
}

export function isPromise(val: Container<any> | Promise<any>): val is Promise<any> {
    return val && (<Promise<any>>val).then !== undefined;
}

Подробнее: https://www.typescriptlang.org/docs/handbook/advanced-types.html

it('should return a promise', function() {
    var result = testedFunctionThatReturnsPromise();
    expect(result).toBeDefined();
    // 3 slightly different ways of verifying a promise
    expect(typeof result.then).toBe('function');
    expect(result instanceof Promise).toBe(true);
    expect(result).toBe(Promise.resolve(result));
});

Не ответ на полный вопрос, но я думаю, что стоит упомянуть об этом в узле.в JS-10 новая функция утиль под названием isPromise был добавлен, который проверяет, является ли объект родным обещанием или нет:

const utilTypes = require('util').types
const b_Promise = require('bluebird')

utilTypes.isPromise(Promise.resolve(5)) // true
utilTypes.isPromise(b_Promise.resolve(5)) // false

Если вы находитесь в асинхронном методе, вы можете сделать это и избежать любой двусмысленности

async myMethod(promiseOrNot){
  const theValue = await promiseOrNot
}

через поиск надежный способ обнаружения асинхронные функции или даже обещания, Я закончил с помощью следующего теста:

() => fn.constructor.name === 'Promise' || fn.constructor.name === 'AsyncFunction'

ES6:

const promise = new Promise(resolve => resolve('olá'));

console.log(promise.toString().includes('Promise')); //true

Comments

    Ничего не найдено.