如何让后来的Promises等到第一个Promise在蓝鸟中完成?

时间:2016-01-22 23:36:50

标签: javascript promise bluebird

我正在尝试将Promises链接起来。这是代码

crawler.cache(url).then(function (cRes) {
  console.log('get from cache');      
  if(cRes) {
    return Promise.resolve(JSON.parse(cRes));
  } else { 
    console.log('no cache');
    crawler.db(url).then(function (result) {
      console.log('get from db');
      return Promise.resolve(JSON.parse(result));
    });
  }
}).then(function fetch(someResult) {
  console.log('fetch data from' + someResult);
});

我希望它会先查看cache,如果它找不到,那么它应该查看db。然后将结果传递给最后一个then以获取结果。

但这是从我的控制台打印的内容。

get from cache
no cache
fetch data from null
get from db

首先它无法在缓存中找到任何内容然后它正在尝试从数据库中获取但它没有等到从数据库中获取完成后它继续fetch data

当最后一个then必须等待其上方的所有内容完成以获得结果然后它可以执行下一个操作时,如何解决此问题?

2 个答案:

答案 0 :(得分:2)

您可以在then延续中返回承诺,这将导致父承诺等到返回的承诺得到满足并采用它的值。

也不需要使用Promise.resolve方法,只需直接返回值即可。

crawler.cache(url).then(function (cRes) {
    if (cRes) {
        console.log('cache result');
        return JSON.parse(cRes);
    } else {
        console.log('no cache');
        return crawler.db(url).then(function (result) {
            return JSON.parse(result);
        });
    }
}).then(function fetch(someResult) {
    console.log('fetch data from' + someResult);
});

加成: 如果要将缓存存储在内存中。您可能不需要从crawler.cache函数返回承诺。

答案 1 :(得分:-2)

OT:我建议你采用一种稍微不同的方法。使用promise的拒绝路径来表示值不可用/无法解析或提供。

通过这种方式,可以更直观地提供(可能是假的)值,或者我们必须从不同的来源(例如db)解析它。

STH。喜欢(伪代码):

crawler.cache = function(url){
    //you will have to adapt this part to your structure.
    //but you get the idea?
    return new Promise(function(resolve, reject){
        if(url in _cache){
            resolve( _cache[url] );
        }else{
            //you can simply reject() without a reason,
            //or you can return an Error-Object, or some message, or whatever ...
            reject({ message: "no cache for " + url });
        }
    });
}

//try to access the value from the cache
crawler.cache(url)
    //if the cache fails (to provide you a value), 
    //try to resolve the value from the db
    .catch(() => crawler.db(url).then(saveToCache)) 

    //parse the result, wether it is from the cache or the db
    //maybe you want to add a second argument to catch the case where the db also fails?
    .then(str => JSON.parse(str));
    //maybe you want to add a catch here, 
    //in case JSON.parse is provided sth false, like a damaged string?