如何让javascript承诺与node+;是否在EJS文件上显示?

如何让javascript承诺与node+;是否在EJS文件上显示?,javascript,html,node.js,asynchronous,ejs,Javascript,Html,Node.js,Asynchronous,Ejs,在说要看医生之前,我已经看过了,他们一点帮助都没有 我有一个以节点为主干的网页。在一个页面上,我需要从NASA的天文学每日图片(APOD)API中获取过去的10幅图像,然后,我需要从发射库API()中获取接下来的5次发射。我的问题是并非所有APOD都会加载(我理解这一点是因为异步请求的性质) 以下是我针对节点后端的简明app.js文件: app.get("/index", function(req, res) { /**Requesting NASA's Astronomy Pictur

在说要看医生之前,我已经看过了,他们一点帮助都没有

我有一个以节点为主干的网页。在一个页面上,我需要从NASA的天文学每日图片(APOD)API中获取过去的10幅图像,然后,我需要从发射库API()中获取接下来的5次发射。我的问题是并非所有APOD都会加载(我理解这一点是因为异步请求的性质)

以下是我针对节点后端的简明app.js文件:

app.get("/index", function(req, res) {
    /**Requesting NASA's Astronomy Picture of the Day**/
    var apod_url = "https://api.nasa.gov/planetary/apod?api_key=[My Key]"
    var apod_img_urls = [];
    var curr_moment = moment();
    for(var i = 0; i < 10; i++) {
        var appended_url = apod_url + "&date=" + curr_moment.subtract(i, "days").format("YYYY-MM-DD");
        request(appended_url, function(error, reponse, body) {
            if(!error && reponse.statusCode == 200) {
                var img_json = JSON.parse(body);
                if(img_json.media_type == "image") {
                    var apod_promise = new Promise(function(resolve, reject){
                        resolve(img_json.hdurl);
                    });
                    apod_img_urls.push(apod_promise);
                }
            } else {
                console.log(error);
            }
        });
    }
    /**************************************************/

    var url = "https://launchlibrary.net/1.3/launch?next=20&mode=verbose";
    request(url, function(error, response, body) {
       if(!error && response.statusCode == 200) {
           var data = JSON.parse(body);
           res.render("index", {data: data, apod_img_urls: apod_img_urls});
       } else {
           console.log(error);
       }
    });
});
app.get(“/index”),函数(req,res){
/**请求NASA提供当天的天文图片**/
var apod_url=”https://api.nasa.gov/planetary/apod?api_key=[我的钥匙]”
var apod_img_url=[];
var curr_矩=矩();
对于(变量i=0;i<10;i++){
var added_url=apod_url+“&date=“+curr_moment.subtract(i,“days”).格式(“YYYY-MM-DD”);
请求(附加的url、函数(错误、响应、正文){
如果(!error&&reponse.statusCode==200){
var img_json=json.parse(body);
if(img_json.media_type==“image”){
var apod_promise=新承诺(函数(解析、拒绝){
解析(img_json.hdurl);
});
apod_img_url.push(apod_promise);
}
}否则{
console.log(错误);
}
});
}
/**************************************************/
变量url=”https://launchlibrary.net/1.3/launch?next=20&mode=verbose";
请求(url、函数(错误、响应、正文){
如果(!error&&response.statusCode==200){
var data=JSON.parse(body);
res.render(“索引”{data:data,apod_img_url:apod_img_url});
}否则{
console.log(错误);
}
});
});
下面是一个EJS代码段

<% apod_img_urls.forEach(function(promise, index) { %>
    <div class="carousel-item <%= (index == 0 ? 'active' : '') %>">
        <div class="w-100 home-image" style="background-image: url('<%= promise.then(function(url) {return url}); %>')"></div>
    </div>
<% }); %>


当我签入源代码时,它显示div的背景图像url是[objectpromise]。按照我的方式,没有图像显示。此外,显示的div数量(即我应该拥有的图像数量)是可变的;有时候是5,有时候是3,有时候是零。我的问题是在另一个请求中呈现页面吗?另外,我如何才能获得实际的图像URL以显示在EJS文件中?

您创建承诺太晚了,在对reequest的异步回调中-需要相当简单的代码重组

一旦所有承诺都在一个数组中,您就需要使用Promise.all等待它们完成

app.get("/index", function(req, res) {
    /**Requesting NASA's Astronomy Picture of the Day**/
    var apod_url = "https://api.nasa.gov/planetary/apod?api_key=[My Key]"
    var promises = [];
    var curr_moment = moment();
    for(var i = 0; i < 10; i++) {
        var appended_url = apod_url + "&date=" + curr_moment.subtract(i, "days").format("YYYY-MM-DD");
        promises.push(new Promise((resolve, reject) => {
            request(appended_url, function(error, reponse, body) {
                if(!error && reponse.statusCode == 200) {
                    var img_json = JSON.parse(body);
                    resolve(img_json.hdurl);
                } else {
                    reject(error);
                    console.log(error);
                }
            });
        }));
    }
    Promise.all(promises).then(apod_img_urls => {
        var url = "https://launchlibrary.net/1.3/launch?next=20&mode=verbose";
        request(url, function(error, response, body) {
           if(!error && response.statusCode == 200) {
               var data = JSON.parse(body);
               res.render("index", {data, apod_img_urls});
           } else {
               console.log(error);
           }
        });
    });
});
现在,您的代码可以写成:

app.get("/index", function(req, res) {
    /**Requesting NASA's Astronomy Picture of the Day**/
    const apod_url = "https://api.nasa.gov/planetary/apod?api_key=[My Key]"
    const curr_moment = moment();
    Promise.all(Array.from({length:10}, (_, i) => {
        const appended_url = apod_url + "&date=" + curr_moment.subtract(i, "days").format("YYYY-MM-DD");
        return requestP(appended_url).then(({response, body}) => JSON.parse(body).hdurl);
    })).then(apod_img_urls => {
        const url = "https://launchlibrary.net/1.3/launch?next=20&mode=verbose";
        return requestP(url).then(({response, body}) => {
            const data = JSON.parse(body);
            return res.render("index", {data, apod_img_urls});
        });
    });
});   

注意:这里有很多ES2015+正在进行中

如果您使用像
请求承诺
这样的承诺返回请求库,那么您可以执行以下操作:

app.get("/index", function(req, res) {
    var apod_url = "https://api.nasa.gov/planetary/apod?api_key=[My Key]"
    var curr_moment = moment();
    var urls = [];
    for(var i = 0; i < 10; i++) {
        urls[i] = apod_url + "&date=" + curr_moment.subtract(i, "days").format("YYYY-MM-DD");
    }
    Promise.all(urls.map(url => rp({ url, json: true})).then((results) => {
      // here you have all results with JSON already parsed for you
      // ...
    }).catch((err) => {
      // handle error
      // make sure to return response to client
      // ...
    });
    // ...
});
然后使用
Promise.all
等待它们全部完成,同时执行:

Promise.all(promises)
  .then(...)
  .catch(...);
或者,如果您使用的是async/await,则:

try {
  let x = await Promise.all(promises);
  ...
} catch (err) {
  ...
}
许多模块,如
axios
request-promise-json
request-promise
都将为您解析json,如果您正确运行,请参阅:

避免自己解析JSON,但如果这样做,请始终将
JSON.parse()
放在
try/catch
(或使用我的小模块)的内部-查看这些答案以了解原因:


如果您想使用promisified“requests”:很容易,然后使用-当然,您也需要知道如何使用承诺-事实上,您正在异步回调中创建承诺-这太晚了如果我使用request promise,我需要做很多更改吗?不太可能,但请稍候,我会在没有请求承诺的情况下发布答案,请求承诺对于代码显示来说可能有点过头了,谢谢你。我知道这必须是一个组织的事情。apod_img_URL有一个问题;由于某些原因,最终url未定义。有共同的解决办法吗?编辑:原来url实际上是未定义的,所以我猜这是API的问题>
Promise.all(promises)
  .then(...)
  .catch(...);
try {
  let x = await Promise.all(promises);
  ...
} catch (err) {
  ...
}