2016-10-05 3 views
2

Я создаю SDK для API с помощью NodeJS, который можно найти here. Моя проблема заключается в том, что когда пользователь объявляет модуль, он дает имя пользователя и пароль, которые мне нужно проверить, и токен, который должен использоваться для будущих вызовов. Итак, этот токен хранится в irecarga.token, и для каждого будущего вызова я буду использовать его для идентификации пользователя. Моя проблема заключается в том, что если пользователь вызывает другую функцию сразу после объявления, объявление, вероятно, не закончится вовремя (потому что это HTTP POST), а токен атрибута будет равен нулю.Функция блокировки на NodeJS

// module declaration which requires a HTTP call and updates irecarga.token 
var irecarga = require('../')({ 
    username: process.env.IRECARGA_USERNAME, 
    password: process.env.IRECARGA_PASSWORD 
}) 

// function called straight after declaration which uses irecarga.token 
irecarga.getServiceProviders(48, function(err, data){ 
    // this code won't even run because the token = null will break the code 
    console.log('err: ', err) 
    console.log('data', data) 
}) 

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

Эти решения, скорее всего, будут работать, но код будет уродливым и беспорядочным. Кроме того, я не думаю, что я новаюсь, на самом деле так я видел, как крупные компании, такие как Microsoft и Google, объявляли свои ключи API.

Я что-то упустил? Есть ли что-нибудь, что я мог бы добавить внутри функции проверки, которая заставит любой метод iRecarga ждать, пока не будет выполнена проверка?

+0

Почему бы вам не использовать обещание. Если вы не хотите, чтобы он был асинхронным, используйте библиотеку, например wait.for, которая делает ваш код последовательным. Но я предпочел бы использовать обещание в любой день. – maddygoround

+0

Взгляните на это: http://stackoverflow.com/questions/20315434/node-js-asynchronous-module-loading Ответ описывает несколько отличных шаблонов. В конечном итоге вам придется использовать один из них, чтобы избежать обратного вызова (или обещания, как указано выше). Но не обязательно, чтобы ваш код был грязным, я не думаю. –

+0

почему вам нужно сделать запрос на отправку при настройке переменных? – Orlando

ответ

0

Использование await вы можете добавить один вкладыш к каждому из методов API, которые будут ждать initializatoin (аутентификация) для завершения с помощью ожидая обещания решить. Вот один из способов сделать это. Я использую последний синтаксис с babel.

// myapi.js 

import login from './auth'; 
import {query, insert} from './db'; 

let authenticated = null, user = null; 

async function getProviders({regionId}) { 
    await authenticated; 
    return await query({region:regionId}); 
} 

async function order({provider, service}) { 
    await authenticated; 
    return await insert({entity:'orders'}, {service, user}); 
} 

export default function ({username, password}) { 
    authenticated = new Promise(async (resolve, reject) => { 
    const valid = await login({username, password}); 
    if (valid) { 
     user = username; 
     resolve(); 
    } else { 
     reject(); 
    } 
    }); 
    return {getProviders, order}; 
} 

// test/myapi.js 

import myapi from '../myapi'; 

async function test() { 
    let api = myapi({username:'tom', password:'1234'}); 
    let providers = await api.getProviders({regionId:48}); 
    console.log(providers); 
    let providers2 = await api.getProviders({regionId:5}); 
    console.log(providers2); 
} 

test().catch(console.error); 
+0

Ответы всегда лучше, если они также содержат некоторое объяснение проблемы OP, а не только код. – jfriend00

+0

Я выбираю это как правильный ответ, потому что ожидание кажется лучшим решением для моего вопроса, поэтому единственным требованием является то, что пользователь использует функции. Тем не менее, я должен отметить, что я не делаю этого в своем SDK, я решил, что каждая функция проверяет токен перед запуском, а если он равен нулю, процесс проверки будет вызываться перед запуском самой функции. – Ernanirst

+0

@ ErnanideSãoThiago - это очень плохое требование использовать SDK. Если вы не планируете использовать это в среде, которой владеете, я не думаю, что это хорошая идея (например, вы не сможете использовать ее в обычной среде JavaScript). 'async/await' является API ES2016 и не поддерживается без babel или другого транспилятора. Лучше задерживать подтверждение имени пользователя/пароля до первого запроса или просто использовать Promises – Orlando

1

В node.js вы не делаете асинхронные вещи в блокирующие вещи. Вместо этого вы используете их как async и создаете поверх них асинхронный интерфейс.

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

  1. Возвращение обещания от require()() с разрешенным значением является вашим объектом модуля. Затем вызывающий выполняет .then(), и в этом обратном вызове может использоваться ваш правильно инициализированный модуль.

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

  3. Не передавать учетные данные конструктору. Вместо этого создайте метод async .login(), который возвращает обещание и инструктирует вызывающих абонентов не использовать интерфейс, кроме как в рамках разрешенного логина.

Например, это может выглядеть следующим образом:

require('../')({ 
    username: process.env.IRECARGA_USERNAME, 
    password: process.env.IRECARGA_PASSWORD 
}).then(function(irecarga) { 
    // function called straight after declaration which uses irecarga.token 
    // this method should probably be changed to use promises 
    irecarga.getServiceProviders(48, function(err, data){ 
     console.log('err: ', err) 
     console.log('data', data) 
    }); 
}).catch(function(err) { 
    // handle intiialization error here 
}); 
+0

Why downvote? Даунвиты, не предлагая причины, не помогают людям лучше отвечать. – jfriend00

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