简体   繁体   English

如何嵌套promise.all

[英]How to nested promise.all

I'm using es6 and have the following promises. 我正在使用es6,并具有以下承诺。 What i want is the next Promise.all to wait for previous Promise.all to be completed before execute the next one. 我想要的是下一个Promise.all,等待上一个Promise.all完成,然后再执行下一个。 I have tried with the below codes but it's not working, only Promise 1 is resolved. 我尝试使用以下代码,但无法正常工作,仅解决了Promise 1。

var deletePromises = [];
arr.menuItems.forEach((item, idx) => {
  if (item.replace) {
     deletePromises.push(deleteFromFirebase(user.uid, item));
  }
});

// Promise 1
Promise.all(deletePromises).then(res1 => {
  var uploadPromises = [],  updateRecordPromises = [];

  arr.menuItems.forEach((item, idx) => {
    uploadPromises.push(uploadToFirebase(user.uid, item));
  });

  // Promise 2
  Promise.all(uploadPromises).then(res2 => {
    arr.menuItems.forEach((item, idx) => {
      item.replace = false;
      updateRecordPromises.push(updateRecord(user.uid, item));
    });

    // Promise 3
    Promise.all(updateRecordPromises).then(res3 => { 
        console.log('All promise execute with successfully');
    });
 });
});

MarkM Answer MarkM回答

Try to use chaining as Mark suggest but the problem still there. 尝试按照Mark的建议使用链接,但是问题仍然存在。 I had found where the problem was, it is uploadPromises that never get resolved and then is never get called. 我发现问题出在哪里,那就是uploadPromises,它永远都不会得到解决,然后再也不会被调用。

uploadToFirebase function uploadToFirebase函数

Stuck here, but the file is successfully uploaded. 卡在此处,但文件已成功上传。 I can see all the files. 我可以看到所有文件。

const uploadToFirebase = (userid, item) => {
 return new Promise((resolve, reject) => {
    const uploadUri = Platform.OS === "ios"
      ? RNFetchBlob.wrap(item.pic_url.replace("file://", ""))
     : RNFetchBlob.wrap(item.pic_url);

    Blob.build(uploadUri, {
      type: "image/png;"
    }).then(blob => {
     // upload image using Firebase SDK
    firebase
    .storage()
    .ref("menu_items")
    .child(userid)
    .child(item.new_filename)
    .put(blob, { contentType: "image/png" })
    .then(snapshot => {
      console.log("Promise resolve: ", snapshot);
      resolve(snapshot);
      blob.close();
    })
    .catch(error => {
      reject(error.message);
    });
  });
 });
};

Updated code 更新的代码

console.log('Print res2') is not printed 未打印console.log('Print res2')

var deletePromises = [],
uploadPromises = [],
updateRecordPromises = [];

arr.menuItems.forEach((item, idx) => {
  if (item.replace) {
    deletePromises.push(deleteFromFirebase(user.uid, item));
  }
});

Promise.all(deletePromises)
.then(res1 => {
  console.log("Print res1:", res1);
  arr.menuItems.forEach((item, idx) => {
    uploadPromises.push(uploadToFirebase(user.uid, item));
  });

  return Promise.all(uploadPromises);
})
.then(res2 => {
  console.log("Print res2:", res2);
  dispatch({ type: MENU_UPDATE_SUCCESS, payload: arr });
  dispatch(reset("menuItem"));
})
.catch(error => {
  console.log("Print error:", error);
});

You don't need to nest the Promises, you can return your new Promise.all from then() , which will let you chain them. 您不需要嵌套Promises,可以从then()返回新的Promise.all ,这将允许您链接它们。 Easier with an example: 举个简单的例子:

var arr = [1, 2, 3, 4, 5, 6]

function slowF(i) {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(i), i*200)
    })
}
var p = arr.map((i) => slowF(i))


Promise.all(p)
.then((p) => {
    console.log("In first Promise.all resolving: ", p)
    var newP = p.map(i => slowF(i) )
    return Promise.all(newP)   
})
.then((p)=>{
    console.log("In second Promise.all resolving: ", p)
})
.catch((e) => console.log("error: ", e))

I found the solution. 我找到了解决方案。 It is because one of menuItems array prop -> new_filename is empty, thats why promise never get resolved. 这是因为menuItems数组prop-> new_filename之一为空,这就是诺言从未得到解决的原因。 So, i just need to add empty checking for each of item prop and then the promise was resolved properly. 因此,我只需要为每个项目道具添加空检查,然后正确解决了诺言。 Thanks to @MarkM for the answer. 感谢@MarkM的答案。 Now the code much more cleaner and easier to read compare to the nested promise. 与嵌套的promise相比,现在的代码更加简洁,易于阅读。

Promise.all(deletePromises)
.then(res1 => {
  console.log("Print res1:", res1);
  arr.menuItems.forEach((item, idx) => {
    if (!isEmpty(item.new_filename)) {
      uploadPromises.push(uploadToFirebase(user.uid, item));
    }
  });

  return Promise.all(uploadPromises);
})
.then(res2 => {
  console.log("Print res2:", res2);
  dispatch({ type: MENU_UPDATE_SUCCESS, payload: arr });
  dispatch(reset("menuItem"));
})
.catch(error => {
  console.log("Print error:", error);
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM