延迟数组$ .when.apply(...)运行得太早

发布时间:2020-07-06 23:38

以下$ .when.apply(...)立即运行,而不是等待发布延迟数组中提供的每个文件的完成。我尝试了许多方法,代码可以正常工作,但是延迟数组的行为就像立即完成一样,而不是先等待所有ajax调用完成。

function handleFiles() {
  showUploadingSpinnerOnModal() 

  var metadata = []
  var rootFolderSelected = $("#root-folder").val()
  var childFolderSelected = $("#child-folder").val()
  metadata["rootFolderName"] = rootFolderSelected
  metadata["childFolderName"] = childFolderSelected

  $.when.apply($, loopThroughFiles(metadata)).then(function(deferredArry) {
      // do something after
      console.log("2: ", deferredArry)
      updateViews()
  })
} 

function loopThroughFiles(metadata) {
  deferredArry = []
  $.each(containerFiles, function(index, file) {
      deferredArray.push(postNewFile(file, metadata))
      console.log("added promise to deferred array");
  })
  return deferredArry
}  

//发布新文件...

function postNewFile(fileObj, metadata) {

    var getFile = getFileBuffer()

    getFile.done(function(arrayBuffer) {
        var addFile = addFileToFolder(arrayBuffer, fileObj)
        addFile.done(function(file, status) {
            var getItem = getListItem(file.d.ListItemAllFields.__deferred.uri)
            getItem.done(function(listItem, status) {
                var changeItem = updateListItem(listItem.d.__metadata, metadata)
                changeItem.done(function(data, status) {
                    console.log("File Uploaded and Metadate Updated")
                })
                changeItem.fail(onError)
            })
            getItem.fail(onError)
        })
        addFile.fail(onError)
    })
    getFile.fail(onError)


    function getFileBuffer() {
        var deferred = $.Deferred()
        var reader = new FileReader()
        reader.onloadend = function(e) {
            deferred.resolve(e.target.result)
        }
        reader.onerror = function(e) {
            deferred.reject(e.target.error)
        }
        reader.readAsArrayBuffer(fileObj)
        return deferred.promise()
    }


    function addFileToFolder(arrayBuffer, fileObj) {
        var apiUrl = PROJECT_BASE_URL + "/_api/web/GetFolderByServerRelativeUrl('documentLibrary')/Files/add(url='" + fileObj.name + "',overwrite=true)"
        return $.ajax({
            url: apiUrl,
            method: 'POST',
            data: arrayBuffer,
            processData: false,
            headers: {
                "accept": "application/json; odata=verbose",
                "contentType": "application/json; odata=verbose",
                "content-Length": arrayBuffer.byteLength,
                "X-RequestDigest": formDigest
            }
        })
    }

    function getListItem(fileURI) {
        return $.ajax({
            url: fileURI,
            type: "GET",
            headers: {
                "accept": "application/json; odata=verbose"
            }
        })
    }

    function updateListItem(fileMetadata) {
        var data = {
            __metadata: {
                'type': 'SP.Data.DocumentlibraryItem'
            }
        }
        data['RootFolder'] = metadata.rootFolderName
        data['ChildFolder'] = metadata.childFolderName

        return $.ajax({
            url: fileMetadata.uri,
            type: 'POST',
            data: JSON.stringify(data),
            async: true,
            headers: {
                "content-type": "application/json;odata=verbose",
                "content-length": data.length,
                "IF-MATCH": fileMetadata.etag,
                "X-HTTP-Method": "MERGE",
                "X-RequestDigest": formDigest
            }
        })
    }
}

function onError(error) {
    console.log(error.responseText)
}
回答1

postNewFile()不返回承诺。实际上,它不会返回任何内容,因此,当您将项目推入数组时,您只是在创建undefined值的数组。因此,您要将undefined个值的数组传递给$.when(),并且由于该数组不包含promise,因此没有任何等待的地方。

您需要正确地从postNewFile()返回一个承诺,只有当该文件中的所有异步操作都完成后,该承诺才会被解决或拒绝。所有这些异步操作也应该正确地链接在一起,以便对它们进行排序,从而使它们的承诺链接在一起(针对完成和错误)。