2015-05-18 2 views
0

У меня есть функция, которая ожидает один аргумент как функции, так и класса, и я должен выполнять разные действия для каждого из двух.Определить, является ли аргумент классом (реализация обещаний +) или вызываемой функцией

Пример псевдокода:

function myFunction(callback) { 
    if (/* callback is a Promise class */) { 
     return new callback(function (resolve, reject) { 
      // logic 
      resolve(); 
     }); 
    } else if (/* callback is a callable function */) { 
     // logic 
     callback(); // Realistically this would not be called at the end of logic block. 
    } else { 
     // throw error 
    } 
} 

Я хотел бы предложить поддержку для произвольной библиотеки Promise реализации А + стандарт, поэтому разработчик может передать то, что реализация они уже используют и не выполнять никаких обходных путей или использовать мою реализацию. Имейте в виду, что я не говорю о собственных реализациях в современных виртуальных машинах, но я также нацелен на other implementations. Опция вызываемой функции существует как резерв, если разработчик не хочет (хочет) использовать библиотеку Promise. Надеюсь, это объяснение имеет смысл.

Из того, что я пробовал, я всегда получаю такой же результат как для класса, так и для вызываемой функции, поскольку классы в JavaScript - это просто функции. Единственным обходным решением, которое я смог сделать, является проверка callback.length, но эта функциональность очень хрупок и, скорее всего, будет ломаться в любом реальном случае использования.

+0

В JavaScript нет такой вещи, как «класс». Что вы подразумеваете под «классом» здесь? – Pointy

+0

@Пожалуйста, прочитайте полный вопрос. В принципе, я хочу знать, могу ли я создать экземпляр аргумента или вызвать его. –

+1

Пожалуйста, просто сделайте лучший интерфейс, который не должен решить эту запутанную проблему. Подобно другому аргументу, который указывает, как должен обрабатываться аргумент обратного вызова. Или передайте объект со свойствами, которые указывают, что это такое. В основном вы создали запутанный интерфейс, и именно поэтому у вас есть эта проблема. – jfriend00

ответ

3

На самом деле нет никакой разницы между произвольными функциями обратного вызова и функциями конструктора.

ES6 добавит некоторые отличия здесь (например, не дает функции стрелки .prototype), но ни один из них не будет надежным.

Единственное реальное различие между конструкторами и «нормальными» функциями является их прототипом. Если вы специально ориентируетесь на реализацию Promise, все серьезные библиотеки будут иметь метод .then().

Таким образом, вы можете использовать

if (typeof callback == "function") 
    if (callback.prototype && typeof callback.prototype.then == "function") 
     // looks like a Promise constructor 
    else 
     // an ordinary function 

Конечно, это не работает на 100% мыслимых случаев. Могут быть и другие классы с методами then, и существуют реализации Promises/A +, которые делают .then() экземпляром вместо метода прототипа. Также не забывайте, что конструктор Promise еще не стандартизирован (он находится в ES6, но не в Promises/A +).


Лучшая идея, чем с помощью шаблона Promise конструктора будет Promise.resolve. Вы просто создали бы произвольный thenable, который затем будет усваиваться каждой реализацией обещания. Вам даже не нужно было бы давать этот резольвер в качестве аргумента, вы должны просто вернуть thenable в отсутствие аргумента функции обратного вызова. Затем ваши потребители могут просто обернуть все вызовы вам API в Promise.resolve(…) из их любимой библиотеки.

Именно так была разработана совместимость Promise в первую очередь, поэтому она будет абсолютно работать.

+0

Спасибо за это, я не думал о '.then'. Я согласен с лучшим решением, но я не совсем понимаю, что вы имеете в виду, можете ли вы привести пример? –

+0

Просто используйте собственный конструктор 'Promise'. Если вы хотите использовать обещания внутри себя, выберите свою любимую библиотеку, если нет, то просто используйте что-то, что строит thenables (которые не должны придерживаться какой-либо спецификации). Затем, если обратный вызов не передан, верните его. Ваши потребители будут бросать их на обещания собственной любимой библиотеки, не передавая вам ничего. – Bergi

+0

Конструктор обещаний стандартизован в спецификации конструктора обещаний так же, как «тогда» стандартизирован в Promises/A +. –

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