按顺序解决承诺不起作用
Resolving Promises sequentially not working
我有一个代码:
- 从 Firebase 读取最后三个数据
- 迭代每个检索到的数据
- 将返回 Promise 的函数表达式推送到一个 Promise 数组中,稍后按顺序处理
- 按顺序处理所述数组
代码:
firebase.database().ref('someRef').limitToLast(3).on('value', snapshot => {
let promiseArray = [];
snapshot.forEach(e => {
promiseArray.push(() => {
firebase.storage().ref(e.key).getDownloadURL().then(url => {
//Do something with URL
//In this case, I print out the url to see the order of URL retrieved
//Unfortunately, the order was incorrect
return 'Resolved, please continue'; //Return something to resolve my Promise
});
});
});
let result = Promise.resolve([]);
promiseArray.forEach(promise => {
result = result.then(promise);
});
});
我想应该已经是正确的了。但是,我想要得到的结果是错误的。我错过了什么?
编辑
我好像漏掉了一点。 在我的 Promise 数组中,我希望第一个函数先解析 Promise it returns,然后再继续第二个函数。
forEach
是一种同步方法。您可以使用 map
创建承诺数组,然后使用 promise.all
.
firebase.database().ref('someRef').limitToLast(3).on('value', snapshot => {
let promiseArray = [];
const promiseArray = snapshot.map(e => firebase.storage().ref(e.key).getDownloadURL());
Promise.all(promiseArray).then((resultArr) => {
// Do anything with your result array
});
}
对于承诺的顺序执行,您可以使用 async await
。
firebase.database().ref('someRef').limitToLast(3).on('value', async (snapshot) => {
let promiseArray = [];
const promiseArray = snapshot.map(e => firebase.storage().ref(e.key).getDownloadURL());
let result;
for(let i = 0; i < promiseArray.length; i++) {
result = await promiseArray[i];
}
});
你应该使用 reduce
。你会在这里找到一个很好的例子:https://decembersoft.com/posts/promises-in-serial-with-array-reduce/
我想通了:显然,我忘了我的函数没有返回 Promise。因此,当我链接 then
时,它不会等待我的 Promise 先解决,因为它一开始甚至没有返回。我基本上是返回一个空值,因此函数会继续,而无需等待之前的 Promise 解决。只需添加 return
即可解决问题:
firebase.database().ref('someRef').limitToLast(3).on('value', snapshot => {
let promiseArray = [];
snapshot.forEach(e => {
promiseArray.push(() => {
return firebase.storage().ref(e.key).getDownloadURL().then(url => { //Add return here
//Do something with URL
//In this case, I print out the url to see the order of URL retrieved
//Unfortunately, the order was incorrect
return 'Resolved, please continue'; //Return something to resolve my Promise
});
});
});
let result = Promise.resolve([]);
promiseArray.forEach(promise => {
result = result.then(promise);
});
});
我有一个代码:
- 从 Firebase 读取最后三个数据
- 迭代每个检索到的数据
- 将返回 Promise 的函数表达式推送到一个 Promise 数组中,稍后按顺序处理
- 按顺序处理所述数组
代码:
firebase.database().ref('someRef').limitToLast(3).on('value', snapshot => {
let promiseArray = [];
snapshot.forEach(e => {
promiseArray.push(() => {
firebase.storage().ref(e.key).getDownloadURL().then(url => {
//Do something with URL
//In this case, I print out the url to see the order of URL retrieved
//Unfortunately, the order was incorrect
return 'Resolved, please continue'; //Return something to resolve my Promise
});
});
});
let result = Promise.resolve([]);
promiseArray.forEach(promise => {
result = result.then(promise);
});
});
我想应该已经是正确的了。但是,我想要得到的结果是错误的。我错过了什么?
编辑
我好像漏掉了一点。 在我的 Promise 数组中,我希望第一个函数先解析 Promise it returns,然后再继续第二个函数。
forEach
是一种同步方法。您可以使用 map
创建承诺数组,然后使用 promise.all
.
firebase.database().ref('someRef').limitToLast(3).on('value', snapshot => {
let promiseArray = [];
const promiseArray = snapshot.map(e => firebase.storage().ref(e.key).getDownloadURL());
Promise.all(promiseArray).then((resultArr) => {
// Do anything with your result array
});
}
对于承诺的顺序执行,您可以使用 async await
。
firebase.database().ref('someRef').limitToLast(3).on('value', async (snapshot) => {
let promiseArray = [];
const promiseArray = snapshot.map(e => firebase.storage().ref(e.key).getDownloadURL());
let result;
for(let i = 0; i < promiseArray.length; i++) {
result = await promiseArray[i];
}
});
你应该使用 reduce
。你会在这里找到一个很好的例子:https://decembersoft.com/posts/promises-in-serial-with-array-reduce/
我想通了:显然,我忘了我的函数没有返回 Promise。因此,当我链接 then
时,它不会等待我的 Promise 先解决,因为它一开始甚至没有返回。我基本上是返回一个空值,因此函数会继续,而无需等待之前的 Promise 解决。只需添加 return
即可解决问题:
firebase.database().ref('someRef').limitToLast(3).on('value', snapshot => {
let promiseArray = [];
snapshot.forEach(e => {
promiseArray.push(() => {
return firebase.storage().ref(e.key).getDownloadURL().then(url => { //Add return here
//Do something with URL
//In this case, I print out the url to see the order of URL retrieved
//Unfortunately, the order was incorrect
return 'Resolved, please continue'; //Return something to resolve my Promise
});
});
});
let result = Promise.resolve([]);
promiseArray.forEach(promise => {
result = result.then(promise);
});
});