Возвращение обещания внутри другого не работает [дубликат]

Увеличение размера кучи не является «исправлением», это «штукатурка», 100% временная. Он снова рухнет в другом месте. Чтобы избежать этих проблем, напишите код высокой производительности.

  1. По возможности используйте локальные переменные.
  2. Убедитесь, что вы выбрали правильный объект (EX: выбор между String, StringBuffer и StringBuilder )
  3. Используйте хорошую систему кода для вашей программы (EX: Использование статических переменных VS нестатические переменные)
  4. Другие материалы, которые могли бы работать с вашим кодом.
  5. Попробуйте перемещаться с помощью multy THREADING
8
задан Bergi 22 June 2016 в 07:02
поделиться

3 ответа

Кажется, что не существует решения, кроме описанного в вопросе обходного пути. Для дальнейшего использования, если вы хотите выполнить (а не разрешить) обещание p со значением val, где val - другое обещание, а затем просто вызвать функцию разрешения обещаний для p с аргументом val не будет работать должным образом. Это заставило бы p быть «заблокировано» в состоянии val, так что p будет выполняться с значением разрешения val после выполнения val (см. spec ).

Вместо этого оберните val в другой объект и разрешите p с этим объектом:

var resolveP;  // Promise resolution function for p

var p = new Promise(
    function(resolve, reject) {
        resolveP = resolve;
    }
);

function fulfillPwithPromise(val) {  // Fulfills p with a promise val
    resolveP({promise: val});
}

p.then(function(res) {
    // Do something as soon as p is fulfilled...

    return res.promise;
}).then(function(res) {
    // Do something as soon as the second promise is fulfilled...
});

Это решение работает, если вы уже знаете, что val это обещание. Если вы не можете делать какие-либо предположения о типе val, вам кажется, что вам не повезло. Либо вы должны всегда переносить значения разрешения обещания в другой объект, либо вы можете попытаться определить, имеет ли val поле then типа «функция» и обертывает его условно.

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

2
ответ дан robamler 17 August 2018 в 17:44
поделиться
  • 1
    Наверное, было бы лучшей идеей ждать больше ответов, прежде чем принимать свои собственные. – user 29 August 2015 в 12:29
  • 2
    Этот Q & amp; A заслуживает большего количества голосов. Это ОГРОМНЫЙ кратковременный нативный Promise s. К счастью, патч прост. – ftor 29 March 2018 в 08:20

Нашел аналогичное решение в процессе перехода от $ q в угловую функцию Promise. Promise.all может быть вариантом (в случае независимых параллельных асинхронных задач) путем передачи вокруг соответствующего объекта или чего-то, украшенного состоянием, передавая его на все, что будет готово, когда это необходимо. В приведенном ниже примере Promise.all обратите внимание на то, как он восстанавливается в одном из обещаний - мне потребовалось некоторое время, чтобы понять, как перенаправить результат цепочки. Результат всего лишь возвращение последнего обещания. Хотя это не отвечает на заголовок вопроса, использование return Promise.reject(<an-object-including-a-promise>) (или разрешения) дает серию и / или группу асинхронных задач совместного доступа и управления на этом пути. В случае выбора, загрузив, затем работая с файлом, я бы обработал обработку событий прогресса: pickFile.then(download,orFailGracefully) с downloadProgress, обработанным в обработчике download onResolve (процесс загрузки не кажется асинхронная задача). Ниже приведены связанные эксперименты в консоли.

var q = {
defer: function _defer(){
    var deferred = { };
    deferred.promise = new Promise(function(resolve, reject){
        deferred.resolve = resolve;
        deferred.reject = reject;
    });
    return deferred;
    }
};

var communityThatCares = q.defer();
communityThatCares.promise.then(function(someGood){
    console.log('someGood', someGood);
    return someGood;
}, function(someBad){
    console.warn('someBad', someBad);
    return someBad;
});

(new Promise(function(resolve, reject){ communityThatCares.about = 'communityThatCares'; setTimeout(resolve,1000, communityThatCares); }))
.then(
function(e){
    console.log(3,e); return e.resolve(e);
}, function(e){
    console.warn(3, e); return e.reject(e);
});

var todo = {
    find:'swan'
};

var greaterGood = [(
(new Promise(function(res,rej){ res(todo); })).then(function(e){ e.stuff = 'things'; return e; }),
(new Promise(function(res,reject){ 
    reject(todo);
})).then(function(e){ return e; }
,function(e){
    console.warn(1,e);
    e.recover = 'uh oh';
    return Promise.resolve(e);
}).then(function(e){ console.log(2,e); return e; }),
(new Promise(function(res,rej){ res(todo); })).then(function(e){ console.log(1,e); e.schedule = 'today'; return e; },function(e){ console.warn(1,e); return e; }).then(function(e){ console.log(2,e); return e; }))
];

var nkay = Promise.all( greaterGood )
.then(function(todo){
    console.log('all',todo[0]); return todo;
}, function(todo){
    console.warn('all',todo[0]); return todo;
});
0
ответ дан jimmont 17 August 2018 в 17:44
поделиться
  • 1
    Могу ли я предложить избежать отложенного антипаттерна , или это преднамеренная часть вашего решения? – Bergi 22 December 2015 в 13:08
  • 2
    Полезные вещи @ Берги. Перед редактированием: вопрос неясен, но, похоже, «как разрешить (или отклонить) обещание с другим обещанием или объектом». на что мой ответ пытается обратиться. Образец кода, по-видимому, не лучший подход к определенной неопределенной проблеме, то есть смешивание событий прогресса с асинхронным запросом / обещаниями для меня не имеет смысла. Было бы лучше удалить ответ или просто приспособиться от Promise.all к обещанию. Затем цепочка (или что-то еще?)? Благодаря! – jimmont 24 December 2015 в 05:29

Хотя разные люди используют разные термины, в общей терминологии, «выполнить» означает пообещать в «успешном» состоянии (в отличие от «отклонения») - состояние, которое будет запускать тогда обработчики then, свисающие это.

Другими словами, вы не можете «выполнить» обещание с обещанием. Вы можете выполнить его со значением. (Кстати, термин «разрешение» обычно означает либо выполнение, либо отклонение.)

. Что вы можете сделать, это вернуть обещание от обработчика .then и это будет иметь эффект по существу заменяя оригинальное обещание возвращенным обещанием.

Вот простой пример:

asyncTask1 . then(asyncTask2) . then(processData)

, где asyncTask1 является обещанием, а asyncTask2 - функцией, которая возвращает обещание. Поэтому, когда asyncTask1 выполняется (выполнено успешно), выполняется asyncTask2, и обещание, возвращенное .then, «отменено» по обещанию asyncTask2, возвращается, так что, когда оно заканчивается, данные могут быть обработан.

Я могу сделать что-то подобное, вызвав Promise.resolve с обещанием в качестве параметра. Это немного неправильно, потому что я не разрешаю обещание в техническом смысле. Вместо этого появившееся новое обещание «заселено» обещанием, в которое я прошел. Это также бесполезно, потому что использование результата точно так же, как использование обещания, которое я прошел:

Promise.resolve(asyncTask2)

ведет себя точно так же как

asyncTask2

(предполагая, что asyncTask2 уже является обещанием, в противном случае Promise.resolve имеет эффект создания обещания, которое немедленно выполняется с переданным значением.)

Просто поскольку вы можете сдать обещание Promise.resolve, вы можете передать обещание функции resolve, предоставленной вам в качестве параметра обратного вызова конструктора обещаний. Если параметр, который вы переходите на resolve, не обещает, обещание немедленно соответствует этому значению. Однако, если параметр, который вы переходите на resolve, является другим обещанием, это обещание «берет на себя тело» обещания, которое вы строите. Иными словами, обещание, которое вы строите, начинает вести себя точно так же, как обещание, переданное resolve.

Под «вести себя точно» я имею в виду, если обещание, которое вы передаете resolve уже выполнено, обещание, которое вы строите, мгновенно выполняется с одинаковым значением. Если обещание, которое вы перешли к resolve, уже отклонено, обещание, которое вы строите, немедленно отклоняется по той же причине. Если обещание, которое вы передаете в resolve, еще не разрешено, тогда любые обработчики then, в которых вы выполняете обещание, которое вы строите, будут вызваны, если и когда будет достигнуто обещание, которое вы переходите на resolve.

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

Поэтому, если я не Отсутствие точки вашего вопроса, pickfile может быть записано как

function pickFile() {
  return new Promise(function(resolve, reject) {
    ...display the file picker...

    // Mock code to pretend the user picked a file
    window.setTimeout(function() {
        resolve('thefile');
    });
}

Я не очень четко понял ваш вопрос, так что это может быть не то, что вы хотите. Просьба уточнить, если вы хотите.

0
ответ дан user 17 August 2018 в 17:44
поделиться
  • 1
    Я думаю, что ОП понимает разницу между решением и выполнением достаточно хорошо. Он действительно хочет выполнить обещание, поскольку обещание - это просто ценность. – Bergi 29 August 2015 в 12:49
  • 2
    Я понимаю, что в разговорной речи, "выполняя" и "разрешение" обещание иногда используется как синонимы. Я использовал термины в смысле спецификации ES6 , что делает четкое различие между ними. В этом смысле функция resolve названа правильно, поскольку спецификация заявляет: «Обещание разрешается, если оно разрешено или если оно« заблокировано », чтобы соответствовать состоянию другого обещания. & Quot; (где «установленный» означает «выполненный или отклоненный»). – robamler 30 August 2015 в 18:44
  • 3
    Проблема с вашей реализацией заключается в том, что файл может быть недоступен сразу после того, как пользователь его выбрал. Если он еще должен быть загружен, я хочу, чтобы загрузка была инициирована и контролировалась с помощью pickFile, но я все еще хочу выполнить обещание, которое возвращается pickFile сразу после того, как пользователь выбрал файл (загрузка должна продолжаться в фон). – robamler 30 August 2015 в 18:44
Другие вопросы по тегам:

Похожие вопросы: