如何在反应js ES6中使用Promise.all

时间:2017-08-16 09:20:51

标签: javascript ajax reactjs

我想要做的是在服务器上传文件,然后获取上传文件的URL并进行预览。文件可以不止一个。为此,我写了以下代码:

 let filesURL=[];
 let promises=[];
 if(this.state.files_to_upload.length>0) {

    for(let i=0; i<this.state.files_to_upload.length; i++) {
        promises.push(this.uploadFilesOnServer(this.state.files_to_upload[i]))
    }

    Promise.all(promises).then(function(result){
        console.log(result);
        result.map((file)=>{
            filesURL.push(file);
        });
    });
    console.log(filesURL);
}
const uploadedFilesURL=filesURL;
console.log(uploadedFilesURL);

console.log(filesURL);为我提供Promise.all返回的值 我只想在Promise.all正确完成时才使用这些值。但是,我面临的问题是,console.log(uploadedFilesURL);行首先考虑Promise.all并且给我undefined值。我认为我没有正确使用承诺,有人可以帮助我吗? uploadFileOnServer代码为:

uploadFilesOnServer(file)
  {
    let files=[];
    let file_id='';

    const image=file;
    getImageUrl().then((response) => {
      const data = new FormData();
      data.append('file-0', image);
      const {upload_url}  = JSON.parse(response);
      console.log(upload_url);

      updateProfileImage(upload_url, data).then ((response2) => {
      const data2 = JSON.parse(response2);
      file_id=data2;
      console.log(file_id);
      files.push(file_id);
      console.log(files);
        });
    });
    return files;
  }

3 个答案:

答案 0 :(得分:3)

您必须在3. + 2.5

.then部分执行此操作
Promise.all()

答案 1 :(得分:2)

不,承诺是异步的,因此,不会按照您的想法运作。如果您想在承诺完成后执行某些操作,则必须将其放入承诺的then回调中。以下是基于您的代码的示例:

uploadFilesOnServer(file) {
  let files=[];
  let file_id='';

  const promise = getImageUrl()
  .then((imageUrlResponse) => {
    const data = new FormData();

    data.append('file-0', file);

    const { upload_url }  = JSON.parse(imageUrlResponse);

    console.log(upload_url);

    return updateProfileImage(upload_url, data);
  })
  .then ((updateImageResponse) => {
    file_id= JSON.parse(updateImageResponse);

    console.log(file_id);

    files.push(file_id);

    console.log(files);

    return files;
  });

  return promise;
}

let filesPromise = Promise.resolve([]);

if(this.state.files_to_upload.length > 0) {
  const promises = this.state.files_to_upload.map((file) => {
    return this.uploadFilesOnServer(file);
  });

  filesPromise = Promise.all(promises).then((results) => {
    console.log(results);

    return [].concat(...results);
  });
}

// This is the final console.log of you (console.log(uploadedFilesURL);)
filesPromise.then((filesUrl) => console.log(filesUrl));

一本关于ES6的一本好书,特别是Promises,这本书Understanding ECMAScript 6 - Nicholas C. Zakas

编辑:

以下是示例代码的简单说明:

  1. uploadFilesOnServer是一个接收文件,上传文件并在将来以承诺的形式完成上传时返回文件URL的函数。承诺在获取网址时会调用then回调。

  2. 通过使用map函数,我们创建了一个url promises列表,我们从列表中每个文件执行uploadFilesOnServer得到的结果。

  3. Promise.all方法等待列表中的所有promise完成,加入url结果列表并创建一个带有url列表结果的promise。我们需要这个,因为无法保证所有承诺会立即完成,我们需要在一次回调中收集所有结果以方便起见。

  4. 我们从then回调中获取了网址。

答案 2 :(得分:0)

这是异步代码的工作方式。如果在异步调用从服务器获取文件后同步调用console.log(filesURL);,则uploadFilesOnServer无法正常工作。

关于您的代码,有几个问题:

1. uploadFilesOnServer(file) { let files=[]; let file_id=''; const image=file; return getImageUrl().then((response) => { const data = new FormData(); data.append('file-0', image); const {upload_url} = JSON.parse(response); console.log(upload_url); updateProfileImage(upload_url, data).then ((response2) => { const data2 = JSON.parse(response2); file_id=data2; console.log(file_id); files.push(file_id); console.log(files); return files; }); }); } 必须返回Promise,因为它是异步的。因此:

Promise.all

2.在您的主要功能正文中,您可以仅在其handler中评估Microsoft.AnalysisServices.Tabular执行的结果。

作为旁注,我建议您使用es7 async / await功能和一些像babel / typescript这样的转录器。这将大大减少编写例如同步代码的嵌套/复杂性。