I have a few async methods that I need to wait for completion before I return from the request. I'm using Promises, but I keep getting the error:
在我从请求返回之前,我需要等待完成的一些异步方法。我正在使用Promises,但我一直收到错误:
Each then() should return a value or throw // promise/always-return
Why is this happpening? This is my code:
这为什么开心呢?这是我的代码:
router.get('/account', function(req, res) {
var id = req.user.uid
var myProfile = {}
var profilePromise = new Promise(function(resolve, reject) {
var userRef = firebase.db.collection('users').doc(id)
userRef.get()
.then(doc => { // Error occurs on this line
if (doc.exists) {
var profile = doc.data()
profile.id = doc.id
myProfile = profile
resolve()
} else {
reject(Error("Profile doesn't exist"))
}
})
.catch(error => {
reject(error)
})
})
// More promises further on, which I wait for
})
2 个解决方案
#1
7
Just avoid the Promise
constructor antipattern! If you don't call resolve
but return a value, you will have something to return
. The then
method should be used for chaining, not just subscribing:
只需避免Promise构造函数反模式!如果您不调用resolve但返回值,则会返回一些内容。 then方法应该用于链接,而不仅仅是订阅:
outer.get('/account', function(req, res) {
var id = req.user.uid
var userRef = firebase.db.collection('users').doc(id)
var profilePromise = userRef.get().then(doc => {
if (doc.exists) {
var profile = doc.data()
profile.id = doc.id
return profile // I assume you don't want to return undefined
// ^^^^^^
} else {
throw new Error("Profile doesn't exist")
// ^^^^^
}
})
// More promises further on, which I wait for:
// profilePromise.then(myProfile => { … });
})
#2
2
In your case firebase.db.collection('users').doc(id)
returning promise
itself, please check firebase snippet to here for node-js.
在您的情况下,firebase.db.collection('users')。doc(id)返回promise本身,请在此处查看firebase片段以获取node-js。
If you have multiple promises and you need to call them one by one then use Promises chaining.
如果你有多个承诺,你需要逐个调用它们然后使用Promises链接。
Please check this article this will help you.
请查看这篇文章,这将对您有所帮助。
Use following code in your case,
在您的情况下使用以下代码,
router.get('/account', function(req, res) {
var id = req.user.uid;
var myProfile = {};
var userRef = firebase.db.collection('users').doc(id)
userRef.get()
.then(doc => {
if (!doc || !doc.exists) {
throw new Error("Profile doesn't exist")
}
var profile = doc.data();
profile.id = doc.id;
myProfile = profile;
return myProfile;
})
.catch(error => {
console.log('error', error);
})
})
And use Promise.all if you have multiple promises and you want's to execute them in once.
如果您有多个承诺并且希望一次执行它们,请使用Promise.all。
The Promise.all(iterable)
method returns a single Promise that resolves when all of the promises in the iterable argument have resolved or when the iterable argument contains no promises. It rejects with the reason of the first promise that rejects.
Promise.all(iterable)方法返回单个Promise,当可迭代参数中的所有promise都已解析或者iterable参数不包含promise时,它将解析。它拒绝了第一个承诺拒绝的原因。
For example:
var promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo1');
});
var promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo2');
});
var promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo3');
});
Promise.all([promise1, promise2, promise3])
.then(result => console.log(result))
//result [foo1, foo2, foo3]
Hopes this will help you !!
希望这会对你有所帮助!!
#1
7
Just avoid the Promise
constructor antipattern! If you don't call resolve
but return a value, you will have something to return
. The then
method should be used for chaining, not just subscribing:
只需避免Promise构造函数反模式!如果您不调用resolve但返回值,则会返回一些内容。 then方法应该用于链接,而不仅仅是订阅:
outer.get('/account', function(req, res) {
var id = req.user.uid
var userRef = firebase.db.collection('users').doc(id)
var profilePromise = userRef.get().then(doc => {
if (doc.exists) {
var profile = doc.data()
profile.id = doc.id
return profile // I assume you don't want to return undefined
// ^^^^^^
} else {
throw new Error("Profile doesn't exist")
// ^^^^^
}
})
// More promises further on, which I wait for:
// profilePromise.then(myProfile => { … });
})
#2
2
In your case firebase.db.collection('users').doc(id)
returning promise
itself, please check firebase snippet to here for node-js.
在您的情况下,firebase.db.collection('users')。doc(id)返回promise本身,请在此处查看firebase片段以获取node-js。
If you have multiple promises and you need to call them one by one then use Promises chaining.
如果你有多个承诺,你需要逐个调用它们然后使用Promises链接。
Please check this article this will help you.
请查看这篇文章,这将对您有所帮助。
Use following code in your case,
在您的情况下使用以下代码,
router.get('/account', function(req, res) {
var id = req.user.uid;
var myProfile = {};
var userRef = firebase.db.collection('users').doc(id)
userRef.get()
.then(doc => {
if (!doc || !doc.exists) {
throw new Error("Profile doesn't exist")
}
var profile = doc.data();
profile.id = doc.id;
myProfile = profile;
return myProfile;
})
.catch(error => {
console.log('error', error);
})
})
And use Promise.all if you have multiple promises and you want's to execute them in once.
如果您有多个承诺并且希望一次执行它们,请使用Promise.all。
The Promise.all(iterable)
method returns a single Promise that resolves when all of the promises in the iterable argument have resolved or when the iterable argument contains no promises. It rejects with the reason of the first promise that rejects.
Promise.all(iterable)方法返回单个Promise,当可迭代参数中的所有promise都已解析或者iterable参数不包含promise时,它将解析。它拒绝了第一个承诺拒绝的原因。
For example:
var promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo1');
});
var promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo2');
});
var promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo3');
});
Promise.all([promise1, promise2, promise3])
.then(result => console.log(result))
//result [foo1, foo2, foo3]
Hopes this will help you !!
希望这会对你有所帮助!!