Skip to content

Instantly share code, notes, and snippets.

@lfades
Created May 23, 2017 22:34
Show Gist options
  • Save lfades/65b1f2bb1d59f720ff794f2d8cc94ebb to your computer and use it in GitHub Desktop.
Save lfades/65b1f2bb1d59f720ff794f2d8cc94ebb to your computer and use it in GitHub Desktop.
Comparación entre async/await y promises utilizando un fragmento de codigo de mi implementación con Stripe.
/**
* async/await
*/
import request from 'request'
import express from 'express'
import { GraphQLError } from 'graphql/error'
import { STRIPE_API_KEY } from '../configs'
const server = express()
const TOKEN_URI = 'https://connect.stripe.com/oauth/token'
// request.post devuelve su resultado en un callback, aquí se convierte en un promise.
// De no hacerlo habría que manejar el callback mas adelante lo cual destruye el flujo.
function stripeOAuthToken (code) {
return new Promise((resolve, reject) => {
request.post({
url: TOKEN_URI,
form: {
client_secret: STRIPE_API_KEY,
grant_type: 'authorization_code',
code
}
}, (error, req, body) => {
if (error) {
reject(error)
} else {
resolve(JSON.parse(body))
}
})
})
}
server.get('/connect/stripe', async (req, res) => {
// el codigo de las siguientes definiciones fue acortado por el bien del ejemplo
const {query} = req
const onError = () => {}
const context = {}
try {
if (!query.code || !query.scope) {
throw new GraphQLError('Invalid query')
}
const {company} = await context.userWithCompany()
// Nota: si se consulta de nuevo por el accessToken de Stripe se elimina el token
// anterior que fue usado (como si la aplicación nunca se hubiera conectado al usuario)
if (company.stripe) {
throw new GraphQLError('Already authorized')
}
const accessToken = await stripeOAuthToken(query.code)
if (accessToken.error) {
return onError(accessToken)
}
company.stripe = {
userId: accessToken.stripe_user_id,
refreshToken: accessToken.refresh_token,
scope: accessToken.scope
}
await company.save()
res.redirect('/home')
} catch (error) {
// estoy utilizando una estructura parecida al error que me trae Stripe
// en caso de que nuestro servidor tenga algún error.
onError(error)
}
})
/**
* Utilizando las promises como si fueran callbacks, aunque el callback-hell es mucho peor
*/
import request from 'request'
import express from 'express'
import { GraphQLError } from 'graphql/error'
import { STRIPE_API_KEY } from '../configs'
const server = express()
const TOKEN_URI = 'https://connect.stripe.com/oauth/token'
// request.post devuelve su resultado en un callback, aquí se convierte en un promise.
// De no hacerlo habría que manejar el callback mas adelante lo cual destruye el flujo.
function stripeOAuthToken (code) {
return new Promise((resolve, reject) => {
request.post({
url: TOKEN_URI,
form: {
client_secret: STRIPE_API_KEY,
grant_type: 'authorization_code',
code
}
}, (error, req, body) => {
if (error) {
reject(error)
} else {
resolve(JSON.parse(body))
}
})
})
}
server.get('/connect/stripe', async (req, res) => {
// el codigo de las siguientes definiciones fue acortado por el bien del ejemplo
const {query} = req
const onError = () => {}
const context = {}
if (!query.code || !query.scope) {
// ya no estoy dentro de un try/catch
// throw new GraphQLError('Invalid query')
return onError('Invalid query')
}
context.userWithCompany()
.then(company => {
// Nota: si se consulta de nuevo por el accessToken de Stripe se elimina el token
// anterior que fue usado (como si la aplicación nunca se hubiera conectado al usuario)
if (company.stripe) {
throw new GraphQLError('Already authorized')
}
stripeOAuthToken(query.code)
.then(accessToken => {
if (accessToken.error) {
onError(accessToken)
} else {
company.stripe = {
userId: accessToken.stripe_user_id,
refreshToken: accessToken.refresh_token,
scope: accessToken.scope
}
}
company.save()
.then(() => {
res.redirect('/home')
})
.catch(onError)
})
.catch(onError)
})
.catch(onError)
})
/**
* promises
*/
import request from 'request'
import express from 'express'
import { GraphQLError } from 'graphql/error'
import { STRIPE_API_KEY } from '../configs'
const server = express()
const TOKEN_URI = 'https://connect.stripe.com/oauth/token'
// request.post devuelve su resultado en un callback, aquí se convierte en un promise.
// De no hacerlo habría que manejar el callback mas adelante lo cual destruye el flujo.
function stripeOAuthToken (code) {
return new Promise((resolve, reject) => {
request.post({
url: TOKEN_URI,
form: {
client_secret: STRIPE_API_KEY,
grant_type: 'authorization_code',
code
}
}, (error, req, body) => {
if (error) {
reject(error)
} else {
resolve(JSON.parse(body))
}
})
})
}
server.get('/connect/stripe', async (req, res) => {
// el codigo de las siguientes definiciones fue acortado por el bien del ejemplo
const {query} = req
const onError = () => {}
const context = {}
if (!query.code || !query.scope) {
// ya no estoy dentro de un try/catch
// throw new GraphQLError('Invalid query')
return onError('Invalid query')
}
let company
context.userWithCompany()
.then(_company => {
// Nota: si se consulta de nuevo por el accessToken de Stripe se elimina el token
// anterior que fue usado (como si la aplicación nunca se hubiera conectado al usuario)
if (_company.stripe) {
throw new GraphQLError('Already authorized')
}
// si no hago lo siguiente no podre utilizar _company en el siguiente .then
company = _company
return stripeOAuthToken(query.code)
})
.then(accessToken => {
if (accessToken.error) {
onError(accessToken)
} else {
company.stripe = {
userId: accessToken.stripe_user_id,
refreshToken: accessToken.refresh_token,
scope: accessToken.scope
}
}
return company.save()
})
.then(() => {
res.redirect('/home')
})
// estoy utilizando una estructura parecida al error que me trae Stripe
// en caso de que nuestro servidor tenga algún error.
.catch(onError)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment