Похоже, общей целью является:
- Для каждой записи в
urls
, вызовите $.get
и ждать его завершения.
- Если он возвращает только ответ без «рядом», держать что один ответ
- Если он возвращает ответ с «рядом», мы хотим, чтобы просить «рядом», а затем сохранить их обоих ,
- Вызвать обратный вызов с помощью
response
, когда вся работа будет выполнена.
Я бы поменял # 2, чтобы вы только вернули обещание и разрешили его с помощью response
.
Ключевой вещь обещаний, что then
возвращает нового обещание, которое будет либо разрешенное с тем, что вы вернетесь из then
(непосредственно, если вы возвращаетесь не-thenable значения, или косвенно, если вы возвращаете thenable, путем рабства к тому, что затем можно). Это означает, что если у вас есть источник обещаний ($.get
, в данном случае), вам почти не нужно использовать new Promise
; просто используйте обещания, которые вы создаете с помощью then
. (. И catch
)
Смотри комментарии:
function testCase(urls) {
// Return a promise that will be settled when the various `$.get` calls are
// done.
return Promise.all(urls.map(function(url) {
// Return a promise for this `$.get`.
return $.get(url)
.then(function(response) {
if (response.meta && response.meta.next) {
// This `$.get` has a "next", so return a promise waiting
// for the "next" which we ultimately resolve (via `return`)
// with an array with both the original response and the
// "next". Note that since we're returning a thenable, the
// promise created by `then` will slave itself to the
// thenable we return.
return $.get(url + "&offset=" + response.meta.next)
.then(function(nextResponse) {
return [response, nextResponse];
});
} else {
// This `$.get` didn't have a "next", so resolve this promise
// directly (via `return`) with an array (to be consistent
// with the above) with just the one response in it. Since
// what we're returning isn't thenable, the promise `then`
// returns is resolved with it.
return [response];
}
});
})).then(function(responses) {
// `responses` is now an array of arrays, where some of those will be one
// entry long, and others will be two (original response and next).
// Flatten it, and return it, which will settle he overall promise with
// the flattened array.
var flat = [];
responses.forEach(function(responseArray) {
// Push all promises from `responseArray` into `flat`.
flat.push.apply(flat, responseArray);
});
return flat;
});
}
Обратите внимание, как мы никогда не используем catch
там; мы откладываем обработку ошибок вызывающему.
Использование:
testCase(["url1", "url2", "etc."])
.then(function(responses) {
// Use `responses` here
})
.catch(function(error) {
// Handle error here
});
testCase
функция выглядит очень долго, но это только из-за замечаний.Здесь без них:
function testCase(urls) {
return Promise.all(urls.map(function(url) {
return $.get(url)
.then(function(response) {
if (response.meta && response.meta.next) {
return $.get(url + "&offset=" + response.meta.next)
.then(function(nextResponse) {
return [response, nextResponse];
});
} else {
return [response];
}
});
})).then(function(responses) {
var flat = [];
responses.forEach(function(responseArray) {
flat.push.apply(flat, responseArray);
});
return flat;
});
}
... и было бы еще более кратким, если бы мы использовали функцию стрелки ES2015 в. :-)
В комментарии вы просили:
Может ли это справиться, если был следующий следующий? Как страница 3 результатов?
Мы можем сделать это с помощью инкапсуляции, что логики в функцию мы используем вместо $.get
, который мы можем использовать рекурсивно:
function getToEnd(url, target, offset) {
// If we don't have a target array to fill in yet, create it
if (!target) {
target = [];
}
return $.get(url + (offset ? "&offset=" + offset : ""))
.then(function(response) {
target.push(response);
if (response.meta && response.meta.next) {
// Keep going, recursively
return getToEnd(url, target, response.meta.next);
} else {
// Done, return the target
return target;
}
});
}
Тогда наш главный testCase
проще:
function testCase(urls) {
return Promise.all(urls.map(function(url) {
return getToEnd(url);
})).then(function(responses) {
var flat = [];
responses.forEach(function(responseArray) {
flat.push.apply(flat, responseArray);
});
return flat;
});
}
Где же вы инициализация 'обещаний'? Я вижу, что ты подталкиваешь к нему, но я не вижу, чтобы ты его создал. –
Что такое 'url'? (Если это массив, обычно это будет множественное число, например, 'urls'.) –
Почему' response.resource = response.resource.concat (v.resource); '? Это каждый раз создает целый новый массив ...? –