[英]Make asynchronous function with promises in JavaScript
我有一個功能
function getImage(url, key) {
return axios({
method: 'get',
url,
responseType: 'stream'
}).then(response => {
s3.upload({
Key: key,
Body: response.data,
ContentType: response.data.headers['content-type'],
ACL: 'public-read'
}, (err, data) => {
return key
});
}).catch(err => {
return '';
});
}
它將下載遠程映像並將其上傳到Amazon S3。 我希望它返回生成的密鑰。
我想使用這樣的功能
const images = ['http://...', 'http://...', ...].map((url, i) => {
return {
url: getImage(url, i)
}
});
由於我的函數getImage()
對於每個URL可能要花費一些時間,因此我想我將不得不使用異步調用,以便確保在移至下一個元素之前該函數已完全完成(否則我會誤解某些內容) ?)。
我想我必須使用諾言,所以解決方案可以是這樣嗎?
function getImage(url, key) {
return new Promise((resolve, reject) => {
return axios({
method: 'get',
url,
responseType: 'stream'
}).then(response => {
s3.upload({
Key: key,
Body: response.data,
ContentType: response.data.headers['content-type'],
ACL: 'public-read'
}, (err, data) => {
resolve(key);
});
}).catch(err => {
reject(err);
});
});
}
然后像這樣使用它:
const images = ['http://...', 'http://...', ...].map((url, i) => {
return {
url: getImage(url, i).then(url => url).catch(err => [])
}
});
如評論中所述,axios是一個承諾。 代碼應該看起來像
function getImage(url, key) {
return axios({
method: 'get',
url,
responseType: 'stream'
}).then(response => {
return new Promise((resolve, reject) => {
s3.upload({
Key: key,
Body: response.data,
ContentType: response.data.headers['content-type'],
ACL: 'public-read'
}, (err, data) => {
if (!err) {
resolve(key);
} else {
reject(err);
}
});
});
});
}
用例是,我從公共API獲取許多博客文章。 所以我正在做類似的事情
const blogPostsOriginal = [
{ title: 'Title', images: ['url1', 'url2'] },
{ title: 'Title', images: ['url1', 'url2'] },
{ title: 'Title', images: ['url1', 'url2'] },
];
const blogPostsFormatted = blogPostsOriginal.map(blogPost => {
return {
title: blogPost.title,
images: blogPost.images.map(url => {
// upload image to S3
return getImage(url);
})
};
});
那么我將如何構建博客文章數組的格式? 問題是,如果發生錯誤,我不想在圖像數組中包含該圖像。 我不確定如何用承諾來檢查這一點。
使用ECMAScript 2017 async
/ await
語法,您可以輕松完成此操作。 修改您聲稱正在工作的腳本的原始形式,如下所示:
async function getImage(url, key) { try { const response = await axios({ method: 'get', url, responseType: 'stream' }) await s3.upload({ Key: key, Body: response.data, ContentType: response.data.headers['content-type'], ACL: 'public-read' }).promise() } catch (error) { // return error return key // since we don't have axios and s3 in here } return key } const blogPostsOriginal = [ { title: 'Title', images: ['url1', 'url2'] }, { title: 'Title', images: ['url1', 'url2'] }, { title: 'Title', images: ['url1', 'url2'] }, ]; Promise.all(blogPostsOriginal.map(async ({ title, images }) => { return { title, images: (await Promise.all(images.map(async (url) => { // get your key here somehow const key = Math.random().toString(36).slice(2, 12).padStart(10, 0) // upload image to S3 return getImage(url, key) }))) // after awaiting array of results, filter out errors .filter(result => !(result instanceof Error)) } })).then(blogPostsFormatted => { // use blogPostsFormatted here console.log(blogPostsFormatted) })
為了解釋有關s3.upload(...).promise()
,我從此處和此處的文檔中得到了這一點 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.