Javascript 链接承诺强制异步

Javascript 链接承诺强制异步,javascript,node.js,es6-promise,Javascript,Node.js,Es6 Promise,我正在使用promises来获取大型相册的图像,并从该相册中随机抽取样本。我已设法请求所有相册,然后将指向图像的链接推送到一组对象 现在我想打印出那个数组,但只有在我实际填充它之后。每当我在末尾添加.then()时,它只打印初始化的空数组 如何强制异步并仅在数组填充后打印它。(我正在底部打印出来) 让findimagestalyst=新承诺(函数(解析、拒绝){ //url选项 常量选项={ 网址:'https://api.imgur.com/3/gallery/hot/time/', 标题:

我正在使用promises来获取大型相册的图像,并从该相册中随机抽取样本。我已设法请求所有相册,然后将指向图像的链接推送到一组对象

现在我想打印出那个数组,但只有在我实际填充它之后。每当我在末尾添加
.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 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)
});

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

由于您使用的是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)
});

因此,这里有几个构建块:

  • 请求imgur相册反映到
    options
    对象中
  • findDumps
    -一个简单的函数,可以根据它筛选相册列表
  • 应用前两个函数并返回大型相册数组的函数。它是一个异步函数,所以它可能使用Promise
  • 获取大型相册阵列中的每一项并接收单个图像的函数。这是一个异步函数,所以,再一次,这是一个承诺
  • 您希望等待,直到收到所有单个图像
  • 最后,您需要一个具有两个属性的对象数组:“dump”和“sample”
  • 让我们试着构造一个例子

    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

    因此,这里有几个构建模块:

  • 请求imgur相册反映到
    options
    对象中
  • findDumps
    -一个简单的函数,可以根据它筛选相册列表
  • 应用前两个函数并返回大型相册数组的函数。它是一个异步函数,所以它可能使用Promise
  • 获取大型相册阵列中的每一项并接收单个图像的函数。这是一个异步函数,所以,再一次,这是一个承诺
  • 您希望等待,直到收到所有单个图像
  • 最后,您需要一个具有两个属性的对象数组:“dump”和“sample”
  • 让我们试着构造一个例子

    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
  • 确保没有处理imgur搜索业务的现有节点模块。在npms.io上搜索