【问题标题】:How to nested promise.all如何嵌套 promise.all
【发布时间】:2017-07-02 12:03:16
【问题描述】:

我正在使用 es6 并有以下承诺。我想要的是下一个 Promise.all 等待前一个 Promise.all 在执行下一个之前完成。我已尝试使用以下代码,但它不起作用,只有 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 答案

尝试按照 Mark 的建议使用链接,但问题仍然存在。我发现问题出在哪里,uploadPromises 永远不会得到解决,然后永远不会被调用。

uploadToFirebase 函数

卡在这里,但文件已成功上传。我可以看到所有文件。

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);
    });
  });
 });
};

更新代码

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);
});

【问题讨论】:

  • Promise.all 返回一个 Promise,当所有传递给 promise.all 的 Promise 都被解析时,该 Promise 被解析。所以你可以像平常一样thenPromise.all调用Promise
  • 我尝试使用 console.log 进行调试,然后是 promise2 。好像已经完全解决了但是没有进入,然后尝试console.log in then of promise2,但是没有打印出来。我在这里做错了什么?

标签: javascript firebase


【解决方案1】:

您不需要嵌套 Promise,您可以从 then() 返回新的 Promise.all,这样您就可以将它们链接起来。举个例子更容易:

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 变量是什么?
【解决方案2】:

我找到了解决方案。这是因为 menuItems 数组 prop -> new_filename 之一是空的,这就是为什么 promise 永远不会得到解决的原因。所以,我只需要为每个项目道具添加空检查,然后正确解决承诺。感谢@MarkM 的回答。现在,与嵌套的 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);
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-20
    • 1970-01-01
    • 2019-03-30
    • 1970-01-01
    • 2018-12-02
    • 2020-02-08
    • 2018-05-11
    相关资源
    最近更新 更多