2016-12-04 1 views
2

Так что я борюсь с этим пару дней, и я нашел решение для этого, но я чувствую, что это не очень хорошо. В настоящее время у меня есть следующее. Мне это не нравится, потому что я вкладываю обещания в обещания. Я не знаю, хорошо ли это, но это не похоже на это.Выполнить другое обещание только в том случае, если первое не получило хороших результатов.

То, что я пытаюсь выполнить с помощью этого кода, - это сначала проверить базу данных кэша на значение, если оно там нет, тогда я проверю реальную базу данных.

Любые советы/рекомендации/указатели/комментарии о том, как сделать это более элегантно?

var getData = function() { 
    var cancel = false 
    var cache = db.getFromCache(query) 
     .then((data) => { 
     // Check if data is up to date 
     if (uptodate) { 
      return Promise.resolve(data) 
     } 
     cancel = true  
     }) 

    return cache 
     .then(() => { 
      if (cancel) 
      return db.getFromDatabase().then(//code) 
    } 
} 

ps: этот код может работать или не запускаться, я только что сделал это быстро для этого вопроса. Я не могу пропустить настоящий код здесь

+0

Почему вы вызываете 'cache()'? Действительно ли 'cache' является функцией, которая возвращает обещание? Это не похоже, что это имеет смысл. – jfriend00

+0

'db.getFromCache' возвращает обещание –

+0

Тогда' cache(), тогда 'просто неправильно и не будет работать. Возможно, вы имеете в виду 'cache.then()'. – jfriend00

ответ

2

Когда вы находитесь в .then() обработчика, вы можете сделать любой из следующих действий:

  1. Возвращает значение - это значение становится разрешенным значением родительского обещания. Таким образом, нет необходимости возвращать Promise.resolve(value). Вы можете просто return value.

  2. Возвращение обещание - Когда вы возвращаетесь обещание, он прикован к родительскому обещанию и родительским обещание не будет решить, пока это новое обещание не решает и решить значение этого возвращается обещание будет разрешенное значение родительское обещание.

  3. сгенерирует исключение - Если .then() обработчик броска, что исключение автоматически перехватывается обещание инфраструктуры и превратилось в отрицание так throw err работает аналогично return Promise.reject(err).

Таким образом, когда вы находитесь в вашем .then() обработчиком, вы можете просто проверить, если данные кэша является действительным, и, если да, то просто вернуть его. В противном случае вернем новое обещание получить данные.

var getData = function() { 
    return db.getFromCache(query).then((data) => { 
     // Check if data is up to date 
     if (uptodate) { 
      // return cached data, will be resolved value of promise 
      return data; 
     } else { 
      // get data from db, return promise that will be chained 
      return db.getFromDatabase(); 
     } 
    }) 
} 

getData().then(...) 

Ваш код гораздо сложнее, чем нужно:

  1. Вам не нужно Promise.resolve(). Вы можете просто вернуть значение.
  2. Вам не нужна переменная cancel. Вы можете выполнить всю свою работу внутри первого обработчика .then().
  3. Вам не нужен второй обработчик .then().
+0

Вы правы, мой код намного сложнее, чем нужно. Это сделало его более ясным. Thnx –

2

Обещания поддерживают цепочку, что означает, что обещание может вернуть другое обещание, и это может вернуть другой и т. Д.

По MDN:

  1. Вы можете передать лямбда (анонимной функции) к затем и если она возвращает обещание, эквивалентное обещание будет подвергаться последующей затем в цепочке методов.
  2. Когда значение просто возвращается изнутри затем лямбда, он будет эффективно возвращать Promise.resolve().

Это означает, что в блоке с затем, вы можете проверить, если data до настоящего времени в кэше. Если data является свежим, верните его, и значение будет завершено в новое обещание. Если данные несвежие, вы можете вернуть вызов getFromDatabase(), который возвращает обещание:

const getData = (query) => db.getFromCache(query) 
    .then((data) => isUpToDate(data) ? data : db.getFromDatabase(query)); 

getData().then(/** code **/); 

Возвращаясь с обещания обертывания возвращаемых данных с новым обещанием, так что вы можете манипулировать данные, и вернуть его, и будет обернут обещание автоматически:

db.getFromDatabase().then((data) => data.map(/** some code **/)); // result will be wrapped in a promise. 
+0

Так что я сделал правильно, а не «противно»? –

+0

Это работает :) Однако это громоздко, и он не использует возможности обещания. –

+0

Да, это слово, которое я искал. Это громоздко. Вот почему я хочу, чтобы все было по-другому. Менее громоздко: P –