如何让后面的 Promise 等待第一个 Promise 在 bluebird 完成?

How to make the later Promises wait for the first Promise to finish in bluebird?

我正在尝试链接 Promise。这是代码

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必须等待上面的所有内容完成才能得到结果才能进行下一步操作,如何解决这个问题?

您可以只 return then 延续中的承诺,这将导致父级承诺等待 returned 承诺完成并采用它的价值。

也不需要用Promise.resolve的方法,直接return这个值就可以了。

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

奖金: 如果您将缓存存储在内存中。您可能不需要 return 来自 crawler.cache 函数的承诺。

OT:我向您推荐一种稍微不同的方法。使用承诺的 rejection-path 传达值未 available/couldn 未被解析或提供。

通过这种方式,无论是提供(可能是虚假的)值,还是我们必须从数据库等不同来源解析该值,都会更加直观。

……喜欢(伪代码):

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?