如何重用承诺? [英] How to reuse promises?

查看:87
本文介绍了如何重用承诺?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试重用promise中返回的数据。但是,问题是,在第一次调用 checkPromise 函数后,它立即调用第二个函数,并且第一个函数的承诺未得到满足,因此它永远不会返回任何函数数据,因此它永远不会进入if子句。如何重用承诺?

I am trying to reuse the the data returned from promise here. But, the problem is, after the first call to checkPromise function, it immediately calls the second function, and the promise for the first function is not fulfilled, so it never returns any data, and hence it never enters the if clause. How do I reuse a promise?

var Promise = require('bluebird');
var request = Promise.promisify(require("request"));


var url = 'http://www.google.com';
var obj = new Object;

function apiCall(url) {
    return new Promise(function (resolve, reject) {

        request(url).spread(function(response, body) {
            return resolve(body);
        }).catch(function(err) {
            console.error(err);
            return reject(err);
        });

    });
}

function checkPromise(url) {
    if(obj.hasOwnProperty(url)) {   
        var rp = obj[url];
        //do something
    }
    else {
        apiCall(url).then(function(result) {            
            obj[url] = result; 
            //do something
        });
    }
}

checkPromise(url);
checkPromise(url);


推荐答案

您可能遇到时间问题。您的 apiCall()函数是异步的。这意味着它会在稍后完成。因此,每次调用 checkPromise()时,您所做的只是启动一个请求,并在稍后完成。所以,你第一次调用它并启动一个请求(尚未完成)。然后,您的下一个 checkPromise()的调用将被调用,如果在第一次调用完成之前检查它是。因此,它在缓存中找不到任何内容。

You likely have a timing issue. Your apiCall() function is asynchronous. That means it finishes sometime later. As such, each time you call checkPromise(), all you're doing is starting a request and it finishes sometime later. So, you call it the first time and it starts a request (that has not finished yet). Then, your next call to checkPromise() gets called and it does it's if check before the first call has completed. Thus, it finds nothing in the cache yet.

您的代码并行运行两个请求,而不是一个接一个地请求。

Your code is running two requests in parallel, not one after the other.

如果你真的想等到第一个请求完成后再执行第二个请求,那么你必须实际构建你的代码来做到这一点。您需要使 checkPromise()返回一个promise本身,因此使用它的代码可以知道它何时实际完成以便在完成后执行某些操作。

If you actually want to wait until the first request is done before executing the second one, then you will have to actually structure your code to do that. You would need to make checkPromise() return a promise itself so code using it could known when it was actually done in order to execute something after it was done.

仅供参考,我的代码中没有看到任何与重用承诺有关的内容(这是你不能做的,因为它们是一次性对象)。

FYI, I don't see anything in your code that is actually related to reusing promises (which is something you cannot do because they are one-shot objects).

这是一种可能的实现方式:

Here's one possible implementation:

var Promise = require('bluebird');
var request = Promise.promisify(require("request"));

var url = 'http://www.google.com';
var obj = {};

function apiCall(url) {
    return request(url).spread(function(response, body) {
        return body;
    });
}

function checkPromise(url) {
    if(obj.hasOwnProperty(url)) {   
        var rp = obj[url];
        //do something
        return Promise.resolve(rp);
    }
    else {
        return apiCall(url).then(function(result) {            
            obj[url] = result; 
            //do something
            return result;
        });
    }
}

checkPromise(url).then(function() {
    checkPromise(url);
});

重大变化:


  1. 返回 request()返回的承诺,而不是再创建另一个承诺。

  2. 更改 checkPromise()因此它始终返回一个promise,无论是否在缓存中找到该值,因此调用代码始终可以一致地工作。

  3. 对两个<$>进行排序c $ c> checkPromise()调用所以第一个可以在第二个执行之前完成。

  1. Return the promise returned by request() rather than create yet another one.
  2. Change checkPromise() so it always returns a promise whether the value is found in the cache or not so calling code can always work consistently.
  3. Sequence the two checkPromise() calls so the first can finish before the second is executed.






如果你感兴趣的结果已经被加载,那么一种非常不同的方法是实际等待缓存。这可以这样做:


A very different approach would be to actually wait on the cache if a result you are interested in is already being loaded. That could be done like this:

var Promise = require('bluebird');
var request = Promise.promisify(require("request"));

var url = 'http://www.google.com';
var obj = {};

function apiCall(url) {
    return request(url).spread(function(response, body) {
        return body;
    });
}

function checkPromise(url) {
    if(obj.hasOwnProperty(url)) {   
        // If it's a promise object in the cache, then loading 
        // If it's a value, then the value is already available
        // Either way, we wrap it in a promise and return that
        return Promise.resolve(obj[url]);
    } else {
        var p = apiCall(url).then(function(result) {
            obj[url] = result; 
            //do something
            return result;
        });
        obj[url] = p;
        return p;
    }
}

checkPromise(url).then(function(result) {
    // use result
});

checkPromise(url).then(function(result) {
    // use result
});

这篇关于如何重用承诺?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆