Javascript 链接承诺强制异步
我正在使用promises来获取大型相册的图像,并从该相册中随机抽取样本。我已设法请求所有相册,然后将指向图像的链接推送到一组对象 现在我想打印出那个数组,但只有在我实际填充它之后。每当我在末尾添加Javascript 链接承诺强制异步,javascript,node.js,es6-promise,Javascript,Node.js,Es6 Promise,我正在使用promises来获取大型相册的图像,并从该相册中随机抽取样本。我已设法请求所有相册,然后将指向图像的链接推送到一组对象 现在我想打印出那个数组,但只有在我实际填充它之后。每当我在末尾添加.then()时,它只打印初始化的空数组 如何强制异步并仅在数组填充后打印它。(我正在底部打印出来) 让findimagestalyst=新承诺(函数(解析、拒绝){ //url选项 常量选项={ 网址:'https://api.imgur.com/3/gallery/hot/time/', 标题:
.then()
时,它只打印初始化的空数组
如何强制异步并仅在数组填充后打印它。(我正在底部打印出来)
让findimagestalyst=新承诺(函数(解析、拒绝){
//url选项
常量选项={
网址:'https://api.imgur.com/3/gallery/hot/time/',
标题:{
“授权”:“客户ID xxxx”
}
};
//初始请求
请求(选项、功能(错误、恢复、正文){
//解析响应
body=JSON.parse(body)
//访问响应中的数据
const responseData=body.data;
//仅过滤图像计数大于50的图像
const largeAlbums=响应数据过滤器(findDumps)
//测试以查看是否存在转储
如果(大磅长度>0){
forEach(函数(i){})
解析(大容量)
}否则{
拒绝
}
})
})
//如果成功找到转储文件,则检查它们并找到它们的AlbumID
.然后(功能(大容量){
让dumpid=largeAlbums.map(index=>index.id)
返回dumpid;
})
//使用相册/转储ID,使用新请求获取每个相册/转储ID
.then(函数(转储ID){
//对于每个dumpid,使用ES6创建所需的url,然后请求它。
dumpIds.forEach(函数(i){
常量albumUrlOptions={
网址:`https://api.imgur.com/3/album/${i}/images`,
标题:{
“授权”:“客户ID xxxx”
}
}
//向每个相册/转储发出请求
请求(选项、函数(错误、恢复、正文){
body=JSON.parse(body)
常量响应数据=body.data
//从相册/转储中选择一个示例图像
让sampleImage=responseData[randomSelector(responseData.length)].link;
推({
“倾销”:我,
“样本”:样本图像
})
})
})
返回转储;
})
.then(函数(转储){
console.log(转储)
})
您是第二位。然后应返回所有(已承诺的)请求
由于您使用的是node.js,它具有非常好的ES2015+实现,因此(在我看来)您可以通过以下方式简化代码:首先,创建一个“promisified version ofrequest
let requestP = (options) => new Promise((resolve, reject) => {
request(options, (err, res, body) => {
if (err) {
return reject(err);
}
resolve({res, body});
});
});
剩下的代码可以按如下方式重新编写
const options = {
url: 'https://api.imgur.com/3/gallery/hot/time/',
headers: {
"Authorization": "Client-ID xxxx"
}
};
//inital request
let findImagesCatalyst = requestP(options)
.then(({res, body}) => {
//parse the response
body = JSON.parse(body)
//access the data in the response
const responseData = body.data;
//filter only those with image counts great than 50
const largeAlbums = responseData.filter(findDumps)
//test to see if a dump is present
if (largeAlbums.length > 0) {
largeAlbums.forEach(function(i) {})
return(largeAlbums)
} else {
return Promise.reject();
}
})
//if successful in finding a dump, then go through them and find their albumIds
.then((largeAlbums) => largeAlbums.map(index => index.id))
//with the album/dump ids, get each of them with a new request
.then((dumpIds) =>
//for each of the dumpIds create the needed url using ES6 and then request it.
Promise.all(dumpIds.map((i) => {
const albumUrlOptions = {
url: `https://api.imgur.com/3/album/${i}/images`,
headers: {
"Authorization": "Client-ID xxxx"
}
};
return requestP(albumUrlOptions)
.then(({res, body}) => {
body = JSON.parse(body)
const responseData = body.data
//pick one sample image from the album/dump
let sampleImage = responseData[randomSelector(responseData.length)].link;
return({
"dump": i,
'sample': sampleImage
});
});
}))
)
.then(function(dumps) {
console.log(dumps)
});
你是第二个。然后应该返回承诺。所有(承诺的)请求 由于您使用的是node.js,它具有非常好的ES2015+实现,因此(在我看来)您可以通过以下方式简化代码:首先,创建一个“promisified version of
request
let requestP = (options) => new Promise((resolve, reject) => {
request(options, (err, res, body) => {
if (err) {
return reject(err);
}
resolve({res, body});
});
});
剩下的代码可以按如下方式重新编写
const options = {
url: 'https://api.imgur.com/3/gallery/hot/time/',
headers: {
"Authorization": "Client-ID xxxx"
}
};
//inital request
let findImagesCatalyst = requestP(options)
.then(({res, body}) => {
//parse the response
body = JSON.parse(body)
//access the data in the response
const responseData = body.data;
//filter only those with image counts great than 50
const largeAlbums = responseData.filter(findDumps)
//test to see if a dump is present
if (largeAlbums.length > 0) {
largeAlbums.forEach(function(i) {})
return(largeAlbums)
} else {
return Promise.reject();
}
})
//if successful in finding a dump, then go through them and find their albumIds
.then((largeAlbums) => largeAlbums.map(index => index.id))
//with the album/dump ids, get each of them with a new request
.then((dumpIds) =>
//for each of the dumpIds create the needed url using ES6 and then request it.
Promise.all(dumpIds.map((i) => {
const albumUrlOptions = {
url: `https://api.imgur.com/3/album/${i}/images`,
headers: {
"Authorization": "Client-ID xxxx"
}
};
return requestP(albumUrlOptions)
.then(({res, body}) => {
body = JSON.parse(body)
const responseData = body.data
//pick one sample image from the album/dump
let sampleImage = responseData[randomSelector(responseData.length)].link;
return({
"dump": i,
'sample': sampleImage
});
});
}))
)
.then(function(dumps) {
console.log(dumps)
});
因此,这里有几个构建块:
options
对象中findDumps
-一个简单的函数,可以根据它筛选相册列表const findImagesCatalyst = new Promise((resolveImagesCatalyst, rejectImagesCatalyst) => {
const options = {
url: 'https://api.imgur.com/3/gallery/hot/time/',
headers: {
Authorization: 'Client-ID xxxx'
}
};
request(options, (err, res, body) => {
//access the data in the response
const responseData = JSON.parse(body).data;
//filter only those with image counts great than 50
const largeAlbums = responseData.filter(findDumps);
//test to see if a dump is present
if (largeAlbums.length > 0) {
// /!\ The trickiest part here: we won't resolve this promise until an "inner Promise" has been resolved.
// Note that next line declares a new function to resolve inner Promise, resolveLargeAlbum. Now we have two functions:
// - resolveImagesCatalyst - to resolve the main Promise, and
// - resolveLargeAlbum — to resolve every image request, and there can be many of them.
const imagesPromises = largeAlbums.map(largeAlbum => new Promise((resolveLargeAlbum, rejectLargeAlbun) => {
// take id from every large album
const dumpId = largeAlbum.id;
// declare options for inner request
const options = {
url: `https://api.imgur.com/3/album/${i}/images`,
headers: {
"Authorization": "Client-ID xxxx"
}
};
request(albumUrlOptions, (err, res, body) => {
const responseData = JSON.parse(body).data;
//pick one sample image from the album/dump
const sampleImage = responseData[randomSelector(responseData.length)].link;
if (sampleImage) {
// A-HA!
// It's inner Promise's resolve function. For N albums, there will be N resolveLargeAlbum calls. Just a few lines below, we're waiting for all of them to get resolved.
resolveLargeAlbum({
dump: dumpId,
sample: sampleImage
});
} else {
rejectLargeAlbun('Sorry, could not receive sample image:', dumpId, responseData);
}
});
}));
// Now we have imagePromises, an array of Promises. When you have an array of Promises, you can use Promise.all to wait until all of them are resolved:
Promise.all(imagesPromises).then(responses => {
// Take a look at responses: it has to be an array of objects of two properties: dump and sample.
// Also, note that we finally use outer Promise's resolve function, resolveImagesCatalyst.
resolveImagesCatalyst(responses);
}).catch(errors => {
rejectImagesCatalyst(errors);
});
} else {
rejectImagesCatalyst('Sorry, nope.');
}
});
});
这是一个很大的问题。你真正需要看到的是
- 使用,您可以等待一组承诺得到解决,“then”部分在所有承诺都得到解决之前不会执行
- 你可以,当内心的承诺得到解决时,解决外在的承诺
- 代码很难阅读,因为执行顺序不是从上到下的。如果你用Babel的Webpack,你可能想看看。使用async/await,代码看起来是同步的:您从上到下读取它,这正是它的执行结果出现的顺序,但在后台,它是异步的。非常整洁的ES6功能,imho
options
对象中findDumps
-一个简单的函数,可以根据它筛选相册列表const findImagesCatalyst = new Promise((resolveImagesCatalyst, rejectImagesCatalyst) => {
const options = {
url: 'https://api.imgur.com/3/gallery/hot/time/',
headers: {
Authorization: 'Client-ID xxxx'
}
};
request(options, (err, res, body) => {
//access the data in the response
const responseData = JSON.parse(body).data;
//filter only those with image counts great than 50
const largeAlbums = responseData.filter(findDumps);
//test to see if a dump is present
if (largeAlbums.length > 0) {
// /!\ The trickiest part here: we won't resolve this promise until an "inner Promise" has been resolved.
// Note that next line declares a new function to resolve inner Promise, resolveLargeAlbum. Now we have two functions:
// - resolveImagesCatalyst - to resolve the main Promise, and
// - resolveLargeAlbum — to resolve every image request, and there can be many of them.
const imagesPromises = largeAlbums.map(largeAlbum => new Promise((resolveLargeAlbum, rejectLargeAlbun) => {
// take id from every large album
const dumpId = largeAlbum.id;
// declare options for inner request
const options = {
url: `https://api.imgur.com/3/album/${i}/images`,
headers: {
"Authorization": "Client-ID xxxx"
}
};
request(albumUrlOptions, (err, res, body) => {
const responseData = JSON.parse(body).data;
//pick one sample image from the album/dump
const sampleImage = responseData[randomSelector(responseData.length)].link;
if (sampleImage) {
// A-HA!
// It's inner Promise's resolve function. For N albums, there will be N resolveLargeAlbum calls. Just a few lines below, we're waiting for all of them to get resolved.
resolveLargeAlbum({
dump: dumpId,
sample: sampleImage
});
} else {
rejectLargeAlbun('Sorry, could not receive sample image:', dumpId, responseData);
}
});
}));
// Now we have imagePromises, an array of Promises. When you have an array of Promises, you can use Promise.all to wait until all of them are resolved:
Promise.all(imagesPromises).then(responses => {
// Take a look at responses: it has to be an array of objects of two properties: dump and sample.
// Also, note that we finally use outer Promise's resolve function, resolveImagesCatalyst.
resolveImagesCatalyst(responses);
}).catch(errors => {
rejectImagesCatalyst(errors);
});
} else {
rejectImagesCatalyst('Sorry, nope.');
}
});
});
这是一个很大的问题。你真正需要看到的是
- 使用,您可以等待一组承诺得到解决,“then”部分在所有承诺都得到解决之前不会执行
- 你可以,当内心的承诺得到解决时,解决外在的承诺
- 代码很难阅读,因为执行顺序不是从上到下的。如果你用Babel的Webpack,你可能想看看。使用async/await,代码看起来是同步的:您从上到下读取它,这正是它的执行结果出现的顺序,但在后台,它是异步的。非常整洁的ES6功能,imho