嵌套 .then() 函数
Nesting .then() functions
嵌套多个 then 函数是不好的做法吗?说 "execute this function, and when it's done, execute this one"(等等)似乎很合乎逻辑,但代码看起来很糟糕。
如果有帮助,我最初是在 firestore 获取用户详细信息然后获取文档的上下文中进行此查询的
firebaseApp.auth().signInWithEmailAndPassword(email, password).catch(function(error) {
//If error
}).then(()=>{
firebaseApp.firestore().collection(collectionName).where("associatedID", "==", authID).get().then((snapshot)=>{
snapshot.docs.forEach(doc => {
//Do stuff with data that we've just grabbed
})
}).then(()=>{
//Tell the user in the UI
});
});
有其他选择吗?脑海里浮现的是这样的
var functionOne = () =>{
console.log("I get called later");
}
var promise1 = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('foo');
}, 3000);
});
promise1.then(function(value) {
functionOne();
});
但即便如此,经过几次 .then() 之后它似乎也会变得复杂
Return 来自第一个外部 .then
的 Promise,然后在第二个外部 .then
中使用解析值,没有任何嵌套 .then
s:
firebaseApp.auth().signInWithEmailAndPassword(email, password)
.then(()=>{
return firebaseApp.firestore().collection(collectionName).where("associatedID", "==", authID).get()
})
.then((snapshot) => {
snapshot.docs.forEach(doc => {
//Do stuff with data that we've just grabbed
});
//Tell the user in the UI
})
.catch((error) => {
// handle errors
});
确保不要 catch
太早 - 如果链中的任何地方出现错误,通常您会希望停止正常执行并直接转到末尾(例如,告诉用户有一个错误)。
如果您担心代码的可读性,请考虑使用 async
/await
(并为旧版浏览器转译您的生产代码):
// in an async function:
try {
await firebaseApp.auth().signInWithEmailAndPassword(email, password);
const snapshot = await firebaseApp.firestore().collection(collectionName).where("associatedID", "==", authID).get()
snapshot.docs.forEach(doc => {
//Do stuff with data that we've just grabbed
});
//Tell the user in the UI
} catch(error) {
// handle errors
}
这取决于你想做什么:如果你需要访问传递给 then
和 的结果以及后续操作的结果同时在then
内做,嵌套合理:
doSomething()
.then(result1 => {
return doSomethingElse()
.then(result2 => {
return result1 + result2;
});
})
.then(combinedResult => {
// Use `combinedResult`...
})
.catch(/*...*/);
不过,通常您只需要通过链传递单个值,方法是从 then
处理程序返回后续操作的承诺:
doSomething()
.then(result => {
return doSomethingElse(result);
})
.then(lastResult => {
// `lastResult` is the fulfillment value from `doSomethingElse(result)`
})
.catch(/*...*/);
这样做会将创建的承诺 then
解析为 get()
在查询中返回的承诺。 (“resolve a promise to something” 意味着你已经让 promise 的解决取决于你解决它的事情。如果你将它解析为另一个承诺,它的解决取决于另一个承诺的解决。)
看看你的 Firebase 示例,我可能会在没有嵌套的情况下这样做:
firebaseApp.auth()
.signInWithEmailAndPassword(email, password)
.then(() => firebaseApp.firestore().collection(collectionName).where("associatedID", "==", authID).get())
.then((snapshot) => {
snapshot.docs.forEach(doc => {
// Do stuff with data
});
})
.then(() => {
// Tell the user in the UI
})
.catch(function(error) {
// Handle/report error, which may be from `signInWithEmailAndPassword`, your collection query, or an error raised by your code in the `then` handlers above
});
您应该链接承诺,并且还可以命名函数,恕我直言,这可以显着提高可读性。考虑这样的事情
const signIn = () => firebaseApp.auth().signInWithEmailAndPassword(email, password);
const onSigninError = (err) => // error handling logic here
const getCollection = () => firebaseApp.firestore().collection(collectionName).where("associatedID", "==", authID)
.get();
const processSnapshot = (snapshot) => snapshot.doc.forEach(// do stuff here
const displayMessage = () => // do stuff here
signIn()
.catch(onSigninError)
.then(getCollection)
.then(processSnapshot)
.then(displayMessage);
嵌套多个 then 函数是不好的做法吗?说 "execute this function, and when it's done, execute this one"(等等)似乎很合乎逻辑,但代码看起来很糟糕。
如果有帮助,我最初是在 firestore 获取用户详细信息然后获取文档的上下文中进行此查询的
firebaseApp.auth().signInWithEmailAndPassword(email, password).catch(function(error) {
//If error
}).then(()=>{
firebaseApp.firestore().collection(collectionName).where("associatedID", "==", authID).get().then((snapshot)=>{
snapshot.docs.forEach(doc => {
//Do stuff with data that we've just grabbed
})
}).then(()=>{
//Tell the user in the UI
});
});
有其他选择吗?脑海里浮现的是这样的
var functionOne = () =>{
console.log("I get called later");
}
var promise1 = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('foo');
}, 3000);
});
promise1.then(function(value) {
functionOne();
});
但即便如此,经过几次 .then() 之后它似乎也会变得复杂
Return 来自第一个外部 .then
的 Promise,然后在第二个外部 .then
中使用解析值,没有任何嵌套 .then
s:
firebaseApp.auth().signInWithEmailAndPassword(email, password)
.then(()=>{
return firebaseApp.firestore().collection(collectionName).where("associatedID", "==", authID).get()
})
.then((snapshot) => {
snapshot.docs.forEach(doc => {
//Do stuff with data that we've just grabbed
});
//Tell the user in the UI
})
.catch((error) => {
// handle errors
});
确保不要 catch
太早 - 如果链中的任何地方出现错误,通常您会希望停止正常执行并直接转到末尾(例如,告诉用户有一个错误)。
如果您担心代码的可读性,请考虑使用 async
/await
(并为旧版浏览器转译您的生产代码):
// in an async function:
try {
await firebaseApp.auth().signInWithEmailAndPassword(email, password);
const snapshot = await firebaseApp.firestore().collection(collectionName).where("associatedID", "==", authID).get()
snapshot.docs.forEach(doc => {
//Do stuff with data that we've just grabbed
});
//Tell the user in the UI
} catch(error) {
// handle errors
}
这取决于你想做什么:如果你需要访问传递给 then
和 的结果以及后续操作的结果同时在then
内做,嵌套合理:
doSomething()
.then(result1 => {
return doSomethingElse()
.then(result2 => {
return result1 + result2;
});
})
.then(combinedResult => {
// Use `combinedResult`...
})
.catch(/*...*/);
不过,通常您只需要通过链传递单个值,方法是从 then
处理程序返回后续操作的承诺:
doSomething()
.then(result => {
return doSomethingElse(result);
})
.then(lastResult => {
// `lastResult` is the fulfillment value from `doSomethingElse(result)`
})
.catch(/*...*/);
这样做会将创建的承诺 then
解析为 get()
在查询中返回的承诺。 (“resolve a promise to something” 意味着你已经让 promise 的解决取决于你解决它的事情。如果你将它解析为另一个承诺,它的解决取决于另一个承诺的解决。)
看看你的 Firebase 示例,我可能会在没有嵌套的情况下这样做:
firebaseApp.auth()
.signInWithEmailAndPassword(email, password)
.then(() => firebaseApp.firestore().collection(collectionName).where("associatedID", "==", authID).get())
.then((snapshot) => {
snapshot.docs.forEach(doc => {
// Do stuff with data
});
})
.then(() => {
// Tell the user in the UI
})
.catch(function(error) {
// Handle/report error, which may be from `signInWithEmailAndPassword`, your collection query, or an error raised by your code in the `then` handlers above
});
您应该链接承诺,并且还可以命名函数,恕我直言,这可以显着提高可读性。考虑这样的事情
const signIn = () => firebaseApp.auth().signInWithEmailAndPassword(email, password);
const onSigninError = (err) => // error handling logic here
const getCollection = () => firebaseApp.firestore().collection(collectionName).where("associatedID", "==", authID)
.get();
const processSnapshot = (snapshot) => snapshot.doc.forEach(// do stuff here
const displayMessage = () => // do stuff here
signIn()
.catch(onSigninError)
.then(getCollection)
.then(processSnapshot)
.then(displayMessage);