Javascript 如何保证

Javascript 如何保证,javascript,firebase,Javascript,Firebase,我正在使用es6,并有以下承诺。我想要的是下一个承诺。全部等待上一个承诺。全部在执行下一个承诺之前完成。我尝试了以下代码,但它不起作用,只有承诺1得到解决 var deletePromises = []; arr.menuItems.forEach((item, idx) => { if (item.replace) { deletePromises.push(deleteFromFirebase(user.uid, item)); } }); // Promise 1

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

尝试使用马克建议的链接,但问题仍然存在。我发现问题出在哪里,是上传的承诺永远不会得到解决,然后再也不会被调用

上传到Firebase函数

卡在此处,但文件已成功上载。我可以看到所有的文件

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

您不需要嵌套承诺,您可以从
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))

您不需要嵌套承诺,您可以从
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))

我找到了解决办法。这是因为menuItems array 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);
});

我找到了解决办法。这是因为menuItems array 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);
});

Promise.all
返回一个承诺,当所有承诺传递给Promise.all时,该承诺将被解析。所以你可以只
然后
这个
承诺。所有
调用都像正常的
承诺
流程一样。我正在尝试使用console进行调试。然后登录promise2。似乎问题已经完全解决,但没有进入,请尝试console.log登录promise2,但没有打印任何内容。我做错了什么?
Promise.all
返回一个Promise,当所有的Promise传递给Promise.all时,该Promise将被解析。所以你可以只
然后
这个
承诺。所有
调用都像正常的
承诺
流程一样。我正在尝试使用console进行调试。然后登录promise2。似乎问题已经完全解决,但没有进入,请尝试console.log登录promise2,但没有打印任何内容。我做错了什么?我在块内的变量是什么?我在块内的变量是什么?