javascript - 链接 promise 强制异步

标签 javascript node.js es6-promise

我使用 promise 来获取大型图像相册,并从该相册中提取随机样本。我已设法请求所有相册,然后将图像链接推送到对象数组。

现在我想打印出该数组,但只有在我实际填充它之后。每当我在末尾添加 .then() 时,它只会打印出初始化的空数组。

我可以做什么来强制异步并仅在数组填满后才打印数组。 (我在底部打印出来)

let findImagesCatalyst = new Promise(function(resolve, reject) {
    //url options 
    const options = {
      url: 'https://api.imgur.com/3/gallery/hot/time/',
      headers: {
        "Authorization": "Client-ID xxxx"
      }
    };

    //inital request
    request(options, function(err, 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) {})
        resolve(largeAlbums)
      } else {
        reject()
      }

    })

  })
  //if successful in finding a dump, then go through them and find their albumIds
  .then(function(largeAlbums) {
    let dumpIds = largeAlbums.map(index => index.id)
    return dumpIds;
  })
  //with the album/dump ids, get each of them with a new request
  .then(function(dumpIds) {
    //for each of the dumpIds create the needed url using ES6  and then request it. 
    dumpIds.forEach(function(i) {
      const albumUrlOptions = {
          url: `https://api.imgur.com/3/album/${i}/images`,
          headers: {
            "Authorization": "Client-ID xxxx"
          }
        }
        //make a request to each of the albums/dumps
      request(albumUrlOptions, function(err, 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;
        dumps.push({
          "dump": i,
          'sample': sampleImage
        })

      })
    })

    return dumps;
  })

.then(function(dumps) {
  console.log(dumps)
})

最佳答案

你是第二个。然后应该返回 Promise。所有( promise 的)请求

.then(function(dumpIds) {
    //for each of the dumpIds create the needed url using ES6  and then request it. 
    return Promise.all(dumpIds.map(function(i) {
        const albumUrlOptions = {
            url: `https://api.imgur.com/3/album/${i}/images`,
            headers: {
                "Authorization": "Client-ID xxxx"
            }
        };
        return new Promise((resolve, reject) => {
            //make a request to each of the albums/dumps
            request(albumUrlOptions, function(err, 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;
                resolve({
                    "dump": i,
                    'sample': sampleImage
                });
            });
        });
    }))
})

由于您使用的是 Node.js,它具有非常好的 ES2015+ 实现,因此您可以通过首先创建“request 的 promise 版本”来简化(在我看来)您的代码

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)
});

关于javascript - 链接 promise 强制异步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41657594/

相关文章:

javascript - 使用 JQuery 和 CSS 在图像上叠加文本?

node.js - TypeError : csv. fromPath 不是函数

javascript - 在 Promise 构造函数之外公开 resolve() 和 reject() 有什么缺点吗?

javascript - jquery 使用 Promise 和反向地理编码获取用户位置

javascript - Javascript中自调用函数的作用域

javascript - 复选框单击事件中的 event.stopPropagation 是否会阻止 IE8 及更早版本中触发更改事件?

javascript - 在 React Native 中更新组件样式的元素

javascript - Node.js In Action Book 回调示例

javascript - 从 url 下载文件并将其上传到 AWS S3 而不保存 - node.js

JavaScript promise : is there any differences between anonymous and not anonymous callbacks?