2016-10-13 3 views
2

Я новичок в Promises и сначала загружаю много результатов из localstorage, и если это не удается, откиньтесь на получение данных с сервера. Я не хочу использовать JQuery - игнорировать, что я в настоящее время использую $ .getJSON: -/сбор нескольких результатов обещаний? (простой javascript)

function loader1() { 
    return new Promise(function (resolve, reject) { 
     localforage.getItem("data1").then(function (value) { 
      if (value !== null) { 
       resolve(value); 
      } else { 
       $.getJSON("/myapp/data1.json").then(function (data) { 
        if (data !== null) { 
         resolve(data); 
        } 
       }).catch(function (err) { 
        reject(err); 
       }); 
      } 
     }); 
    }); 
} 

, который прекрасно подходит для одного файла. Так тогда я

loader1().then(function(result) { 
    // we have a result 
    doSomethingElse(); 
}).catch(function (err) { 
    // problem 
}); 

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

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

Promise 
    .all([loader1, loader2, loader3]) 
    .then(function(result1,result2,result3)) { 
     ... 

, но это не то, как это работает ... поэтому я попытался

Promise 
    .all([loader1, loader2, loader3]) 
    .then(function(result)) { 
     // var result1 = result[0]; 
     // var result2 = result[1]; 
     // var result3 = result[1]; 

но результаты второго являются функции не возвращаемые значения. ..

Поиск по многим сайтам показал, что системы обещаний типа Q и bluebird имеют метод spread, который выглядит так, как я хочу. могу ли я сделать это на простом старом javascript (как?), или я должен использовать вместо этого библиотеку, например Q или RSVP?

+0

Возможный дубликат [Лучший способ es6 получить результаты, основанные на имени, с помощью Promise.all] (http: // stackoverflow.com/questions/35297446/best-es6-way-to-get-name-based-results-with-prom-all) – jib

ответ

0

но результаты второго являются функции не возвращаемые значения. ..

Вы не разрешаете никакого значения, которое вы строите с помощью Promise. Вы также не возвращаете никаких значений из следующих .then в цепочке. Вам необходимо выполнить следующие действия для каждого из ваших функций загрузчика:

function loader1() { 

    var data = localforage.getItem("data1"); 

    data.then(function (data) { 

     if (data !== null) { 
      return data; 
     } else { 
      data = $.getJSON("/myapp/data1.json") 

      if (data !== null) { 
       return data; 
      } else { 
       return Error; 
     } 

    data.catch(function (err) { 
     return (err); 
    } 

Это гарантирует, что вызов функции loader1() будет либо вернуть разрешенную Promise ог отвергнутого Promise. Затем вы можете использовать решение, предложенное guest271314:

Promise 
.all([loader1(), loader2(), loader3()]) 
.then(function(result) { 
    // var result1 = result[0]; 
    // var result2 = result[1]; 
    // var result3 = result[1]; 
}) 
.catch(function (err) { 
    // problem 
}); 

Однако имейте в виду, что Promise выполняет синхронно. Это означает, что он не будет автоматически ждать каких-либо асинхронных действий для завершения внутри Promise. Вы должны позаботиться об этом сами, разрешив его только после завершения асинхронного действия (обычно путем разрешения в обратном вызове, переданного асинхронной функции).

+0

'localforage.getItem' сам возвращается с обещанием. Разве это высказывание не разрешается при вызове localforage (возможно, оно еще не разрешилось). То есть, если «localforage» терпит неудачу, то резерв на получение данных через xhr/в другом месте, тогда если все это не удастся отвергнуть все. – frumbert

+0

Я обновил свой ответ в соответствии с вашей информацией о том, что 'local forage.getItem' возвращает' Promise'. – rabbitco

+0

Также вы должны заметить, что даже если '.then' автоматически возвращает' Promise', вам все равно нужно вернуть что-то внутри переданной ему функции обратного вызова, иначе '.then' вернет' Promise' со значением 'undefined ' – rabbitco

0

Вы можете использовать destructuring:

Promise.all([loader1(), loader2(), loader3()]) 
.then(function([result1, result2, result3]) { 
    ...