Просто сохраните их внутри замыкания.
var makePromise = function () {
var resolvePromise = null,
rejectPromise = null,
promise = new Promise(function (resolve, reject) {
resolvePromise = resolve;
rejectPromise = reject;
});
return { promise : promise, resolve : resolvePromise, reject : rejectPromise };
};
var deferredSomething = function () {
var deferredThing = makePromise();
waitAWhile()
.then(doStuff)
.then(function (result) {
if (result.isGood) {
deferredThing.resolve(result.data);
} else {
deferredThing.reject(result.error);
}
});
return deferredThing.promise;
};
На самом деле это большая часть различий между концепцией «отложенный» и концепцией «обещание»; еще один уровень сверху, на котором есть фактические пульты дистанционного управления, которые вы можете передать кому-то еще, в то время как вы передаете .then|.success|.done|etc...
своим потребителям.
После того, как вы перенесете эти функции в свой восходящий процесс, вы можете счастливо лениво загружать все, что хотите, используя «thenable», который вы вернете, а затем успешно или неудачно выполните свою цепочку (или оставьте ее висящей) по желанию. ..
ОБНОВИТЬ
Учитывая, что этот ответ, вероятно, по-прежнему будет выбранным ответом и по-прежнему будет отвергаться как решение точной проблемы, с которой он столкнулся (то есть: модификация кода, который не был сделан с учетом обещаний ES6), я полагаю, что я добавим более подробный пример того, почему выборочное использование этого антипаттерна может быть лучше, чем ничего:
MongoClient.connect("mongodb://localhost:21017/mydb", (err, db) => {
db.collection("mycollection", (err, collection) => {
collection.find().toArray((err, results) => {
doStuff(results);
});
});
});
Если бы я написал библиотеку здесь, надеясь достичь точки, в которой я мог бы написать:
let dbConnected = MongoClient.connect(dbURL);
dbConnected
.then(db => db.collection(myCollection))
.then(collection => collection.find(query))
.then(stream => doStuff(stream));
... или альтернативно:
composeAsync(
(stream) => doStuff(stream),
(collection) => collection.find(query),
(db) => dbCollection(myCollection)
)(dbConnected);
... для простоты использования в библиотеке, имеет ли смысл обернуть каждое тело функции внутри созданного промиса // find = curry(query, collection) return new Promise(resolve, reject) { /* все тело функции , здесь / / делают много вещей, которые не имеют отношения к разрешению mongo.db.collection.find, но имеют отношение к его вызову */ collection.find(query).toArray( /node-callback/(ошибка, результат) { if (ошибка) { отклонение(ошибка); } else { разрешение(результат); } }); };
... или, глядя на шаблон, действительно требующий только разрешения обратного вызова для конкретного узла, имеет ли смысл иметь какую-то форму промис-преобразователя, чтобы избавить от необходимости записывать/копировать-вставлять полдюжины чисто-избыточные строки, которые надо полностью высушить?
// find = curry(query, collection)
let resolver = new NodeResolver();
collection.find(query).toArray(promise.resolve);
return resolver.promise;
Да, это антишаблон... ...и тем не менее антишаблон, который требует меньшего количества нажатий клавиш, восстанавливает естественный ход цепочки промисов, устраняет проблему с API-интерфейсом Node только для обратного вызова, снижает вероятность ошибок и т. д. так далее.
Да, уже есть библиотеки, которые делают это... ...решения, специфичные для библиотеки X или Y... ...или решения, которые глобально переопределяют методы различных модулей (страшно) ...или решения, которые, опять же, в основном заставить вас передать все детали звонка, который вы делаете:
wrapNodeMethod(fs, "read", url, config).then(data => { /*...*/ });
Но нет простого решения для обращения всей этой боли без:
а) обертывание всего тела функции в обещание, чтобы передать асинхронный обратный вызов преобразователю; б) использование антипаттерна в библиотеке, чтобы передать обратные вызовы Node в преобразователь, о котором остальная часть тела функции точно ничего не должна знать.
Даже если данные необходимо преобразовать в распознавателе, все равно имеет смысл возвращать преобразованный набор в новом промисе.
let resolver = new NodeResolver();
somethingAsync(resolver.resolve);
return resolver.promise.then(transformData).then(logTransform);
... чем обернуть все тело, включая преобразования и т. д., только для справки по области закрытия, просто ради того, чтобы избежать «антипаттерна», который явно идет вразрез с тем, что стало очень заметной платформой/парадигмой JS.
Лично я был бы более счастлив, если бы методы IO||Node возвращали обещание и/или поток, а также принимали обратный вызов в качестве основной части платформы... ...такого не произойдет. ..
... но вы не можете сказать мне, что писать меньше и оставлять модули Node СУХИМИ, в то же время используя ES6 Promises, является «антипаттерном», поэтому не предоставляя мне более красноречивого решения.
Если вы действительно можете предоставить мне что-то, что я могу использовать в любом обратном вызове NodeJS, что действительно обеспечивает более красноречивое решение этой проблемы, так что мне не нужно оборачивать каждое тело каждый метод, который содержит асинхронный обратный вызов в новом конструкторе, или использует неуклюжие методы диспетчера, или захватывает целые модули, чтобы переопределить их глобальную функциональность...
... Я был бы более чем готов отказаться от своего заявления о том, что этот конкретный шаблон по-прежнему очень полезен в отношении взаимодействия с API, которые склонны к пирамидам o'dewm.
person
Norguard
schedule
18.02.2014
$(function() {}
в jQuery является анти-шаблоном, так как я прошу ту же функциональность, за исключением того, что это только одно событие (дом готов), он может быть основан на специальных событиях: функции регистрации для вызова по событию, если функции зарегистрированы после вызова события, они будут вызываться сразу с теми же аргументами. Если вы можете найти способ сделать это без анти-шаблона, пожалуйста, поделитесь им. Просто сказать, что вам это на самом деле не нужно, никому не поможет, и это все равно, что сказать, что нам на самом деле не нужноDOM ready
. - person Nucleon   schedule 03.05.2014