2017-08-25 41 views
1

問題異步函數,該函數不等到地圖將完成如何使基於承諾

我認爲解決方案是Promise.all 但我不知道如何使用此功能

exports.createProduct = (data) => { 
    var imgS3arr = []; //array which we waiting for 
    data.img.map((img, i) => { 
    fetch.remote(img).then((base) => { 
     var buf = Buffer.from(base[0], 'base64'); 

     var imgS3 = { 
      Key: data.title + i, //TODO: add random 
      Body: buf, 
      ContentEncoding: 'base64', 
      ContentType: 'image/jpeg' 
     }; 

     s3Bucket.putObject(imgS3, function (err, data) { 
      if (err) { 
       console.log(err); 
       console.log('Error uploading data: ', data); 
      } else { 
       var params = this.request.params; 
       var region = this.request.httpRequest.region; 
       imgS3arr.push('https://s3-' + region + '.amazonaws.com/' + params.Bucket + '/' + params.Key) 
      } 
     } 
    ); 
    }).catch((reason) => { }); 
}); 

//next part of code must be executed when all items pushed to 'imgS3arr' 

const product = new Product({ 
    title: data.title, 
    img: imgS3arr, //we waiting for this array 
}); 
return product.save((function (err) { 
    if (err) { 
     console.log(err); 
    } else { 
     console.log('Added new! \n' + product); 
    } 
    })); 
} 

可有一個人幫我這個麻煩?

+0

您混合定期回調和承諾異步。首先要做的就是將這段代碼中的所有異步操作轉換爲promise。然後,用'Promise.all()'等待將是微不足道的。 – jfriend00

回答

0

你可以做這樣的事情:

// returns a promise that is resolved when everything is done 
// or rejected with the first error that occurs 
exports.createProduct = (data) => { 
    var imgS3arr = []; //array which we waiting for 
    return Promise.all(data.img.map((img, i) => { 
     return fetch.remote(img).then((base) => { 
      var buf = Buffer.from(base[0], 'base64'); 

      var imgS3 = { 
       Key: data.title + i, //TODO: add random 
       Body: buf, 
       ContentEncoding: 'base64', 
       ContentType: 'image/jpeg' 
      }; 

      return s3Bucket.putObject(imgS3).promise().then(function(data) { 
       // given other changes here and unfamiliarity with this code 
       // I'm unsure if `this` still has the right value in it here 
       var params = this.request.params; 
       var region = this.request.httpRequest.region; 
       imgS3arr.push('https://s3-' + region + '.amazonaws.com/' + params.Bucket + '/' + params.Key) 
      }).catch(function(err) { 
       // log error, then rethrow to keep the promise rejected 
       console.log(err); 
       console.log('Error uploading data: ', data); 
       throw err; 
      }); 
     }); 
    })).then(function() { 
      const product = new Product({ 
       title: data.title, 
       img: imgS3arr, //we waiting for this array 
      }); 
      // use database interface that uses promises, not plain callbacks 
      return product.save(...); 
     } 
    }); 
} 

總結和解釋所做的更改:

  1. 裏面的data.img.map(),返回一個承諾,因此.map()創建承諾的數組。
  2. 承諾進行陣列上使用Promise.all()知道,當他們完成所有的工作。
  3. 切換到s3Bucket.putObject(imgS3).promise()所以我們可以使用的承諾,而不是簡單的回調。
  4. 重新拋出錯誤.catch()登錄狀態,這樣的承諾後撐拒絕要等待Promise.all().then()處理器中
  5. 將代碼。
  6. 切換product.save()的數據庫接口使用的承諾,而不是簡單的回調,所以你可以直接鏈中的承諾(左爲OP做到,因爲我們甚至不知道它是什麼數據庫)。