Unhandled promise rejection?
up vote
4
down vote
favorite
This example (repl.it) (from this answer) looks to me like it follows all the rules regarding promises. Yet running it logs an exception regarding an unhandled promise rejection with the associated console message. (This also happens in FF, Chrome, and Node v10.)
The try/catch block is clearly there and wraps the rejected promise, so what's going on and how would I fix it?
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const delay1 = res(3000)
const delay2 = res(2000)
const delay3 = rej(1000)
const data1 = await delay1
const data2 = await delay2
const data3 = await delay3
} catch (error) {
console.log(`await finished`, Date.now() - start)
}
}
example()
javascript promise async-await
add a comment |
up vote
4
down vote
favorite
This example (repl.it) (from this answer) looks to me like it follows all the rules regarding promises. Yet running it logs an exception regarding an unhandled promise rejection with the associated console message. (This also happens in FF, Chrome, and Node v10.)
The try/catch block is clearly there and wraps the rejected promise, so what's going on and how would I fix it?
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const delay1 = res(3000)
const delay2 = res(2000)
const delay3 = rej(1000)
const data1 = await delay1
const data2 = await delay2
const data3 = await delay3
} catch (error) {
console.log(`await finished`, Date.now() - start)
}
}
example()
javascript promise async-await
add a comment |
up vote
4
down vote
favorite
up vote
4
down vote
favorite
This example (repl.it) (from this answer) looks to me like it follows all the rules regarding promises. Yet running it logs an exception regarding an unhandled promise rejection with the associated console message. (This also happens in FF, Chrome, and Node v10.)
The try/catch block is clearly there and wraps the rejected promise, so what's going on and how would I fix it?
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const delay1 = res(3000)
const delay2 = res(2000)
const delay3 = rej(1000)
const data1 = await delay1
const data2 = await delay2
const data3 = await delay3
} catch (error) {
console.log(`await finished`, Date.now() - start)
}
}
example()
javascript promise async-await
This example (repl.it) (from this answer) looks to me like it follows all the rules regarding promises. Yet running it logs an exception regarding an unhandled promise rejection with the associated console message. (This also happens in FF, Chrome, and Node v10.)
The try/catch block is clearly there and wraps the rejected promise, so what's going on and how would I fix it?
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const delay1 = res(3000)
const delay2 = res(2000)
const delay3 = rej(1000)
const data1 = await delay1
const data2 = await delay2
const data3 = await delay3
} catch (error) {
console.log(`await finished`, Date.now() - start)
}
}
example()
javascript promise async-await
javascript promise async-await
edited Nov 11 at 3:44
asked Nov 10 at 21:57
Ouroborus
6,1521533
6,1521533
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
7
down vote
accepted
The problem is that, at the point that the rej
call rejects, the interpreter hasn't yet gotten to a line that await
s the promise created by rej
, so the rejected Promise is just that, a rejected Promise, rather than a Promise that the current thread is await
ing:
try {
const delay1 = res(3000)
const delay2 = res(2000)
const delay3 = rej(1000)
const data1 = await delay1
// The interpreter is paused on the line above when `rej` rejects
const data2 = await delay2
const data3 = await delay3
So, the behavior is the same as if a rejected Promise is declared without a catch
handler. (Errors thrown by Promises will only be caught in an async
function if they're await
ed at the point at which the Promise rejects - otherwise, it'll just result in an unhandled promise rejection.)
I'd suggest either declaring Promises at the same point that you await
them:
const data1 = await res(3000)
(note: the above method's timing won't be the same as the original code)
or use await Promise.all
for all Promises, which means that the Promise
the interpreter is currently await
ing will throw (and thereby enter the catch
block) as soon as one of the Promises rejects:
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000)
]);
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()
To do additional work while the three Promises are ongoing, and catch errors from those Promises as well as from the main thread, pass a fourth item to the Promise.all
, an IIFE that does the additional work you want to do:
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
(() => {
console.log('doing work...');
})()
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()
Separating the calls and theawait
like in the original example allows something to be done while the async stuff is working. It seems like you're saying that it's not possible to do this kind of separation without resorting to.catch()
?
– Ouroborus
Nov 10 at 22:24
1
If you want to do additional things while still catching errors thrown by the three Promises, use thePromise.all
method (plus a fourth non-Promise that does whatever other stuff you want to do), see edit. No need for.catch
in addition to} catch
– CertainPerformance
Nov 10 at 22:44
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
7
down vote
accepted
The problem is that, at the point that the rej
call rejects, the interpreter hasn't yet gotten to a line that await
s the promise created by rej
, so the rejected Promise is just that, a rejected Promise, rather than a Promise that the current thread is await
ing:
try {
const delay1 = res(3000)
const delay2 = res(2000)
const delay3 = rej(1000)
const data1 = await delay1
// The interpreter is paused on the line above when `rej` rejects
const data2 = await delay2
const data3 = await delay3
So, the behavior is the same as if a rejected Promise is declared without a catch
handler. (Errors thrown by Promises will only be caught in an async
function if they're await
ed at the point at which the Promise rejects - otherwise, it'll just result in an unhandled promise rejection.)
I'd suggest either declaring Promises at the same point that you await
them:
const data1 = await res(3000)
(note: the above method's timing won't be the same as the original code)
or use await Promise.all
for all Promises, which means that the Promise
the interpreter is currently await
ing will throw (and thereby enter the catch
block) as soon as one of the Promises rejects:
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000)
]);
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()
To do additional work while the three Promises are ongoing, and catch errors from those Promises as well as from the main thread, pass a fourth item to the Promise.all
, an IIFE that does the additional work you want to do:
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
(() => {
console.log('doing work...');
})()
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()
Separating the calls and theawait
like in the original example allows something to be done while the async stuff is working. It seems like you're saying that it's not possible to do this kind of separation without resorting to.catch()
?
– Ouroborus
Nov 10 at 22:24
1
If you want to do additional things while still catching errors thrown by the three Promises, use thePromise.all
method (plus a fourth non-Promise that does whatever other stuff you want to do), see edit. No need for.catch
in addition to} catch
– CertainPerformance
Nov 10 at 22:44
add a comment |
up vote
7
down vote
accepted
The problem is that, at the point that the rej
call rejects, the interpreter hasn't yet gotten to a line that await
s the promise created by rej
, so the rejected Promise is just that, a rejected Promise, rather than a Promise that the current thread is await
ing:
try {
const delay1 = res(3000)
const delay2 = res(2000)
const delay3 = rej(1000)
const data1 = await delay1
// The interpreter is paused on the line above when `rej` rejects
const data2 = await delay2
const data3 = await delay3
So, the behavior is the same as if a rejected Promise is declared without a catch
handler. (Errors thrown by Promises will only be caught in an async
function if they're await
ed at the point at which the Promise rejects - otherwise, it'll just result in an unhandled promise rejection.)
I'd suggest either declaring Promises at the same point that you await
them:
const data1 = await res(3000)
(note: the above method's timing won't be the same as the original code)
or use await Promise.all
for all Promises, which means that the Promise
the interpreter is currently await
ing will throw (and thereby enter the catch
block) as soon as one of the Promises rejects:
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000)
]);
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()
To do additional work while the three Promises are ongoing, and catch errors from those Promises as well as from the main thread, pass a fourth item to the Promise.all
, an IIFE that does the additional work you want to do:
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
(() => {
console.log('doing work...');
})()
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()
Separating the calls and theawait
like in the original example allows something to be done while the async stuff is working. It seems like you're saying that it's not possible to do this kind of separation without resorting to.catch()
?
– Ouroborus
Nov 10 at 22:24
1
If you want to do additional things while still catching errors thrown by the three Promises, use thePromise.all
method (plus a fourth non-Promise that does whatever other stuff you want to do), see edit. No need for.catch
in addition to} catch
– CertainPerformance
Nov 10 at 22:44
add a comment |
up vote
7
down vote
accepted
up vote
7
down vote
accepted
The problem is that, at the point that the rej
call rejects, the interpreter hasn't yet gotten to a line that await
s the promise created by rej
, so the rejected Promise is just that, a rejected Promise, rather than a Promise that the current thread is await
ing:
try {
const delay1 = res(3000)
const delay2 = res(2000)
const delay3 = rej(1000)
const data1 = await delay1
// The interpreter is paused on the line above when `rej` rejects
const data2 = await delay2
const data3 = await delay3
So, the behavior is the same as if a rejected Promise is declared without a catch
handler. (Errors thrown by Promises will only be caught in an async
function if they're await
ed at the point at which the Promise rejects - otherwise, it'll just result in an unhandled promise rejection.)
I'd suggest either declaring Promises at the same point that you await
them:
const data1 = await res(3000)
(note: the above method's timing won't be the same as the original code)
or use await Promise.all
for all Promises, which means that the Promise
the interpreter is currently await
ing will throw (and thereby enter the catch
block) as soon as one of the Promises rejects:
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000)
]);
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()
To do additional work while the three Promises are ongoing, and catch errors from those Promises as well as from the main thread, pass a fourth item to the Promise.all
, an IIFE that does the additional work you want to do:
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
(() => {
console.log('doing work...');
})()
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()
The problem is that, at the point that the rej
call rejects, the interpreter hasn't yet gotten to a line that await
s the promise created by rej
, so the rejected Promise is just that, a rejected Promise, rather than a Promise that the current thread is await
ing:
try {
const delay1 = res(3000)
const delay2 = res(2000)
const delay3 = rej(1000)
const data1 = await delay1
// The interpreter is paused on the line above when `rej` rejects
const data2 = await delay2
const data3 = await delay3
So, the behavior is the same as if a rejected Promise is declared without a catch
handler. (Errors thrown by Promises will only be caught in an async
function if they're await
ed at the point at which the Promise rejects - otherwise, it'll just result in an unhandled promise rejection.)
I'd suggest either declaring Promises at the same point that you await
them:
const data1 = await res(3000)
(note: the above method's timing won't be the same as the original code)
or use await Promise.all
for all Promises, which means that the Promise
the interpreter is currently await
ing will throw (and thereby enter the catch
block) as soon as one of the Promises rejects:
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000)
]);
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()
To do additional work while the three Promises are ongoing, and catch errors from those Promises as well as from the main thread, pass a fourth item to the Promise.all
, an IIFE that does the additional work you want to do:
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
(() => {
console.log('doing work...');
})()
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
(() => {
console.log('doing work...');
})()
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()
async function example() {
const start = Date.now()
let i = 0
function res(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
console.log(`res #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
function rej(n) {
const id = ++i
return new Promise((resolve, reject) => {
setTimeout(() => {
reject()
console.log(`rej #${id} called after ${n} milliseconds`, Date.now() - start)
}, n)
})
}
try {
const [data1, data2, data3] = await Promise.all([
res(3000),
res(2000),
rej(1000),
(() => {
console.log('doing work...');
})()
]);
} catch (error) {
console.log(`error caught: await finished`, Date.now() - start)
}
}
example()
edited Nov 10 at 22:47
answered Nov 10 at 22:05
CertainPerformance
66.6k143152
66.6k143152
Separating the calls and theawait
like in the original example allows something to be done while the async stuff is working. It seems like you're saying that it's not possible to do this kind of separation without resorting to.catch()
?
– Ouroborus
Nov 10 at 22:24
1
If you want to do additional things while still catching errors thrown by the three Promises, use thePromise.all
method (plus a fourth non-Promise that does whatever other stuff you want to do), see edit. No need for.catch
in addition to} catch
– CertainPerformance
Nov 10 at 22:44
add a comment |
Separating the calls and theawait
like in the original example allows something to be done while the async stuff is working. It seems like you're saying that it's not possible to do this kind of separation without resorting to.catch()
?
– Ouroborus
Nov 10 at 22:24
1
If you want to do additional things while still catching errors thrown by the three Promises, use thePromise.all
method (plus a fourth non-Promise that does whatever other stuff you want to do), see edit. No need for.catch
in addition to} catch
– CertainPerformance
Nov 10 at 22:44
Separating the calls and the
await
like in the original example allows something to be done while the async stuff is working. It seems like you're saying that it's not possible to do this kind of separation without resorting to .catch()
?– Ouroborus
Nov 10 at 22:24
Separating the calls and the
await
like in the original example allows something to be done while the async stuff is working. It seems like you're saying that it's not possible to do this kind of separation without resorting to .catch()
?– Ouroborus
Nov 10 at 22:24
1
1
If you want to do additional things while still catching errors thrown by the three Promises, use the
Promise.all
method (plus a fourth non-Promise that does whatever other stuff you want to do), see edit. No need for .catch
in addition to } catch
– CertainPerformance
Nov 10 at 22:44
If you want to do additional things while still catching errors thrown by the three Promises, use the
Promise.all
method (plus a fourth non-Promise that does whatever other stuff you want to do), see edit. No need for .catch
in addition to } catch
– CertainPerformance
Nov 10 at 22:44
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53243811%2funhandled-promise-rejection%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown