簡體   English   中英

在函數鏈上返回承諾

[英]Returning promises up a function chain

下面是我寫的一些代碼的結構。 我正在嘗試使用 ajax 將多個文件加載到服務器,一旦所有文件都完成,請執行一些操作。

function func1(items){
 const results = []
 for (let i=0; i<items.length; i++) {
    results[i] = func2();
 }

 Promise.all(results).then(response => some_action())
}

function func3(params) {

  return new Promise((resolve, reject) => {
    //ajax call here and resolve/reject
  })
}

function func2(){

 if(stuff){
   return func3(some_params);
 } else {
   return func3(other_params);   
 }

}

不幸的是,它沒有按我預期的那樣工作。 results數組不是promise數組,而是undefined數組。 我是 Javascript 承諾的新手,所以任何幫助將不勝感激。

編輯:為了回應關於無聲返回可能性的評論,我發布了 func2 的實際代碼(稍作修改):

function func2(item, id, id2, top_level, path){

  if(item.isFile){
    item.file(function(file) {
      if(file.name.substring(file.name.lastIndexOf('.')+1) === "docx"){
        file = new File([file], file.name, {
          type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
        })
      }
      if(file.name !== "desktop.ini"){
        let url = 'url'
        return func3(file, id, url, "", false);
      }
    });
  } else {

      window.parent.ipcRenderer.send('zip-folder', path);

      window.parent.ipcRenderer.on('zipped', (event, buffer) => {
        var zipped_file = new File([buffer], item.name + ".zip", {
          type: "application/zip"
        })
        let url = "/url"
        return func3(zipped_file, id, url, id2, true);
      })

  }
}

您需要在每個函數中返回新的 Promise !

您的else塊不返回任何內容:

...
else {

  window.parent.ipcRenderer.send('zip-folder', path);

  window.parent.ipcRenderer.on('zipped', (event, buffer) => {
    var zipped_file = new File([buffer], item.name + ".zip", {
      type: "application/zip"
    })
    let url = "/url"
    return func3(zipped_file, id, url, id2, true);
  })

  // silently returns undefined
}

不要被匿名函數中的 return 語句所迷惑。 它返回匿名函數,而不是func2

  window.parent.ipcRenderer.on('zipped',                         return this
                                         (event, buffer) => {  <----------.
      var zipped_file = new File([buffer], item.name + ".zip", {          |
        type: "application/zip"                                           |
      })                                                                  |
      let url = "/url"                                                    |
      return func3(zipped_file, id, url, id2, true);   -------------------'
    }
  )

如果您在不使用匿名函數的情況下重寫代碼,這將更加明顯:

function func4(id, url, id2) {
  return function (event, buffer) {
    var zipped_file = new File([buffer], item.name + ".zip", {
      type: "application/zip"
    })
    let url = "/url"
    return func3(zipped_file, id, url, id2, true);
  }
}

function func2(item, id, id2, top_level, path){

  if(item.isFile){
    item.file(function(file) {
      if(file.name.substring(file.name.lastIndexOf('.')+1) === "docx"){
        file = new File([file], file.name, {
          type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
        })
      }
      if(file.name !== "desktop.ini"){
        let url = 'url'
        return func3(file, id, url, "", false);
      }
    });
  } else {

      window.parent.ipcRenderer.send('zip-folder', path);

      window.parent.ipcRenderer.on('zipped', func4(id, url, id2))

      // no return statement !!
  }
}

繞過它的一種方法是將其轉換為承諾:

return new Promise((ok,fail) => {
  window.parent.ipcRenderer.on('zipped', (event, buffer) => {
    var zipped_file = new File([buffer], item.name + ".zip", {
      type: "application/zip"
    })
    let url = "/url"
    ok(func3(zipped_file, id, url, id2, true));
  })
});

當然,根據您的錯誤邏輯如何流動,您可能希望在更高級別包裝承諾。 這僅說明了快速修復。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM