避免在javascript中循环多次返回-async/await以解决回调金字塔或回调地狱,
我有这段代码,有很多返回块,例如SignUp() 连接器.js避免在javascript中循环多次返回-async/await以解决回调金字塔或回调地狱,,javascript,node.js,express,ecmascript-6,ecmascript-2017,Javascript,Node.js,Express,Ecmascript 6,Ecmascript 2017,我有这段代码,有很多返回块,例如SignUp() 连接器.js const connectors = { Auth: { signUp(args) { return new Promise((resolve, reject) => { // Validate the data if (!args.email) { return reject({
const connectors = {
Auth: {
signUp(args) {
return new Promise((resolve, reject) => {
// Validate the data
if (!args.email) {
return reject({
code: 'email.empty',
message: 'Email is empty.'
});
} else if (!isEmail(args.email)) {
return reject({
code: 'email.invalid',
message: 'You have to provide a valid email.'
});
}
if (!args.password) {
return reject({
code: 'password.empty',
message: 'You have to provide a password.'
});
}
return encryptPassword(args.password, (err, hash) => {
if (err) {
return reject(new Error('The password could not be hashed.'));
}
return User.create(Object.assign(args, { password: hash }))
.then((user) => {
resolve(createToken({ id: user._id, email: user.email }));
})
.catch((err2) => {
if (err2.code === 11000) {
return reject({
code: 'user.exists',
message: 'There is already a user with this email.'
});
}
return reject(err2);
});
});
});
},
};
module.exports = connectors;
然后是另一个调用此代码的代码:
const connectors = require('./connectors');
CallsignUp(root, args) {
const errors = [];
return connectors.Auth.signUp(args)
.then(token => ({
token,
errors
}))
.catch((err) => {
if (err.code && err.message) {
errors.push({
key: err.code,
value: err.message
});
return { token: null, errors };
}
throw new Error(err);
});
}
如何在ES6、ES7或ES2017中避免这种情况
有:
return()
.then()
return()
.then
只需循环返回:
return()
return()
return()
从PHP提交这段代码看起来很疯狂,因为返回函数就是返回函数,我不清楚javascript中的名称如何表示这种类型的块返回代码?调用再次返回更多代码的函数
更新:
代码不是我的,源代码完整
我想通过例子来理解:
return encryptPassword(args.password, (err, hash) => {
if (err) {
return reject(new Error('The password could not be hashed.'));
}
return User.create(Object.assign(args, { password: hash }))
.then((user) => {
.catch((err2) => {
return reject(err2);
/src/utils/auth.js(这里是加密密码)
调用函数和返回值和函数有3个返回?OOP从来不是这样的,如何使用@dashmud建议的Async/Await,我不想先学习回调之类的老东西。代码中没有循环 如果您来自PHP,那么我猜Javascript的异步执行模型对您来说是陌生的。我建议学习更多关于Javascript的知识 按以下顺序学习以下内容:
Async/await是最具可读性的,但如果您了解Async/await是如何产生的,那就更好了,因为如果您不了解自己在做什么,它们很容易使用错误的方式。首先要做的事情。代码中没有循环 如果您来自PHP,那么我猜Javascript的异步执行模型对您来说是陌生的。我建议学习更多关于Javascript的知识 按以下顺序学习以下内容:
Async/await是最具可读性的,但如果您了解Async/await是如何产生的,那就更好了,因为如果您不了解自己在做什么,它们很容易以错误的方式使用。此代码需要以多种方式重构。首先,您真的,真的不想在同一逻辑流中混合承诺和普通异步回调。它把事情搞得一团糟,破坏了承诺的许多好处。然后,在
newpromise()
中有一个反模式正在使用承诺。然后,您需要更多的嵌套(您可以改为链)
以下是我的建议:
function encryptPasswordPromise(pwd) {
return new Promise((resolve, reject) => {
encryptPassword(pwd, (err, hash) => {
err ? reject(new Error("The password could not be hashed.")) : resolve(hash);
});
});
}
const connectors = {
Auth: {
signUp(args) {
// Validate the data
let err;
if (!args.email) {
err = {code: 'email.empty', message: 'Email is empty.'};
} else if (!isEmail(args.email)) {
err = {code: 'email.invalid', message: 'You have to provide a valid email.'};
} else if (!args.password) {
err = {code: 'password.empty', message: 'You have to provide a password.'};
}
if (err) {
return Promise.reject(err);
} else {
return encryptPasswordPromise(args.password).then(hash => {
args.password = hash;
return User.create(args);
}).then((user) => {
return createToken({id: user._id, email: user.email});
}).catch(err2 => {
if (err2.code === 11000) {
throw new Error({code: 'user.exists', message: 'There is already a user with this email.'});
} else {
throw err2;
}
});
}
}
}
};
更改摘要:
Promise.reject(err)
encryptPassword()
,这样您就不会将常规回调与promise逻辑流混为一谈,然后可以正确地返回和传播错误return new Promise()
删除对整个代码的包装,因为您的所有异步操作现在都已完成,所以您可以直接返回承诺。这也确实有助于正确的错误处理Object.assign()
,因为似乎没有原因在编辑中,您要求对此代码段进行解释:
return encryptPassword(args.password, (err, hash) => {
if (err) {
return reject(new Error('The password could not be hashed.'));
}
return User.create(Object.assign(args, { password: hash }))
.then((user) => {
.catch((err2) => {
return reject(err2);
encryptPassword()
未定义的
,因此返回
所做的一切都是控制程序流(退出包含函数),但由于在相同级别的返回之后没有代码,因此这是不必要的encryptPassword()
。该回调是异步的,这意味着它将在一段时间后调用err
和hash
。在node.js异步调用约定中,如果第一个参数是truthy(例如,包含一些truthy值),则表示错误。如果为false(通常为null
),则没有错误,第二个参数包含异步操作的结果reject
没有返回值,因此return
仅用于在该点退出回调(因此回调运行中没有其他代码)User.create()
User.create()
User.create()
完成时,它将解析其承诺,这将导致调用.then()
回调,并将结果传递给它。如果该操作出错,则不会调用.then()
回调,而是调用.catch()
回调。在该.catch()
回调中,父承诺被拒绝。这是一种承诺反模式(在另一个承诺中解析父承诺),因为在正确的错误处理中很容易出错。我的回答说明了如何避免这种情况这段代码需要以多种方式重构。首先,您真的,真的不想在同一逻辑流中混合承诺和普通异步回调。它把事情搞得一团糟,破坏了承诺的许多好处。然后,在
newpromise()
中有一个反模式正在使用承诺。然后,你有更多的巢
return encryptPassword(args.password, (err, hash) => {
if (err) {
return reject(new Error('The password could not be hashed.'));
}
return User.create(Object.assign(args, { password: hash }))
.then((user) => {
.catch((err2) => {
return reject(err2);
const encryptPasswordPromise = require('util').promisify(encryptPassword)
const connectors = {
Auth: {
async signUp (args) {
const { email, password } = args
// Validate the data
let err
if (!email) {
err = { code: 'email.empty', message: 'Email is empty.' }
} else if (!isEmail(email)) {
err = { code: 'email.invalid', message: 'You have to provide a valid email.' }
} else if (!password) {
err = { code: 'password.empty', message: 'You have to provide a password.' }
}
if (err) {
throw err
}
let hash
try {
hash = await encryptPasswordPromise(password)
} catch (err) {
throw new Error('The password could not be hashed.')
}
const { _id: id, email } = await User.create(Object.assign(args, { password: hash }))
try {
return createToken({ id, email })
} catch (err) {
if (err.code === 11000) {
throw { code: 'user.exists', message: 'There is already a user with this email.' }
} else {
throw err
}
}
}
}
}
module.exports = connectors