使用 JavaScript 中的承诺创建异步函数
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。我想要它 return 生成的密钥。
我想使用这样的功能
const images = ['http://...', 'http://...', ...].map((url, i) => {
return {
url: getImage(url, i)
}
});
因为我的函数 getImage()
对每个函数 URL 都可能需要一点时间,我想我将不得不使用异步调用,这样我才能确定该函数在移动之前已完全完成进入下一个元素(或者我误解了什么?)。
我想我必须使用 promises,那么解决方案可能是这样的吗?
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);
}
});
});
});
}
编辑 2
用例是我从 public 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);
})
};
});
那么我将如何构建博客文章数组的格式?问题是如果发生错误,我不想将图像包含在图像数组中。我不确定如何用 promises 检查这个。
使用 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()
的部分,我从文档 here and here 中得到了它。
参考资料
我有一个功能
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。我想要它 return 生成的密钥。
我想使用这样的功能
const images = ['http://...', 'http://...', ...].map((url, i) => {
return {
url: getImage(url, i)
}
});
因为我的函数 getImage()
对每个函数 URL 都可能需要一点时间,我想我将不得不使用异步调用,这样我才能确定该函数在移动之前已完全完成进入下一个元素(或者我误解了什么?)。
我想我必须使用 promises,那么解决方案可能是这样的吗?
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);
}
});
});
});
}
编辑 2
用例是我从 public 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);
})
};
});
那么我将如何构建博客文章数组的格式?问题是如果发生错误,我不想将图像包含在图像数组中。我不确定如何用 promises 检查这个。
使用 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()
的部分,我从文档 here and here 中得到了它。