Показать сообщение отдельно
  #4 (permalink)  
Старый 17.12.2016, 11:28
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

Спасибо за мнение! К сожалению ваш код не решает проблему,
promise = new Promise(function(resolve){
	setTimeout(function(){console.log("first run"); resolve(100)}, 1000)
})
Здесь resolve(100) не может быть вызвано раньше, чем сработает setTimeout...



Сообщение от fuckingquest Посмотреть сообщение
А какой смысл его заставлять выполнится, если данные еще не готовы?
Они готовы, но находятся не внутри функций "промиса". Другой вариант -- заставить "промис" передумать, т. е. как вызвать reject() извне?

Простая обёртка вокруг каждого "промиса" позволяет добиться такого результата
function defer(promise) {
	var resolvingFunctions;
	var promise = new Promise(function(resolve, reject) {
		resolvingFunctions = { resolve, reject };
	});
	
	promise.resolve = resolvingFunctions.resolve;
	promise.reject = resolvingFunctions.reject;

	return promise;
}

// Пример
var promise = defer();
promise.then(function() {
	console.log("5+");
});

// "промис", выполнись!
promise.resolve();


Однако мне не нравится отдельный объект(который впринципе не нужен) и то, что придётся оборачивать "промисы", поэтому вопрос о том, как вызвать resolve() остаётся актуальным.
Т. е. как написать resolve/reject в Promise.prototype, я не представляю... Проблема в том, что нет доступа к resolvingFunctions из 8 пункта.

When the Promise function is called with argument executor the following steps are taken:
1. If NewTarget is undefined, throw a TypeError exception.
2. If IsCallable(executor) is false, throw a TypeError exception.
3. Let promise be OrdinaryCreateFromConstructor(NewTarget, "%PromisePrototype%", «‍[[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]]» ).
4. ReturnIfAbrupt(promise).
5. Set promise's [[PromiseState]] internal slot to "pending".
6. Set promise's [[PromiseFulfillReactions]] internal slot to a new empty List.
7. Set promise's [[PromiseRejectReactions]] internal slot to a new empty List.'
8. Let resolvingFunctions be CreateResolvingFunctions(promise).
9. Let completion be Call(executor, undefined, «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»).
10. If completion is an abrupt completion, then
	a. Let status be Call(resolvingFunctions.[[Reject]], undefined, «completion.[[value]]»).
	b. ReturnIfAbrupt(status).
11. Return promise.

(Цитата из спецификации ECMA http://www.ecma-international.org/ec...omise-executor)

Эта цитата навеяла меня на то, что если resolvingFunctions в 9 пункте используются в функций, к которой есть доступ, то можно переписать конструктор "промиса"
(function(root, nativePromise) {
	function Promise(executor) {
		var resolvingFunctions;
		var promise = new nativePromise(function(resolve, reject) {
			resolvingFunctions = { resolve, reject };

			executor.call(undefined, resolve, reject);
		});

		promise.resolve = resolvingFunctions.resolve;
		promise.reject = resolvingFunctions.reject;

		return promise;
	}

	// это потребовалось, поскольку переопределён конструктор
	// и следовательно статичные методы улетели, возвращаем на место
	"race reject resolve".split(" ").forEach(function(method) {
		Promise[method] = nativePromise[method];
	});

	// теперь Promise.resolve() instanceof Promise === false
	// поскольку nativePromise !== Promise, исправляем
	Object.defineProperty(Promise, Symbol.hasInstance, {
		value: function(instance) {
			return instance instanceof nativePromise;
		}
	})

	Promise.prototype.constructor = Promise;

	root.Promise = Promise;
})(this, Promise);


Можно сказать проблема решена, если кто более гениально не придумает!

Впринципе теперь можно легко создать промис, который может передумать!
var promise = new Promise(function(resolve) {
	setTimeout(resolve, 2500);
});

promise.then(function() {
	alert("Свершилось!");
});

// Если вызвать эту функцию раньше чем выполнится "промис",
// то он никогда не выполнится
function nowIThinkAnotherWay() {
	promise.reject();
}


Рабочии пример http://codepen.io/Malleys/pen/VmqdeN?editors=0010
Ответить с цитированием