使用Javascript本机承诺,在附加了thenables之后解决承诺 [英] Using Javascript native promises, resolve a promise after thenables attached

查看:72
本文介绍了使用Javascript本机承诺,在附加了thenables之后解决承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法使用javascript本机承诺( docs )创建一个promise并附上thenables,而不知道构造函数时间它将如何解决?

Is there a way using javascript native promises (docs) to create a promise and attach thenables, without knowing at constructor time how it will resolve?

var foo = new Promise(function(resolve, reject) {
    // I don't know how this will resolve yet as some other object will resolve it
});

foo.then(function(val) {
  console.log("first " + val);
});

foo.resolve("bar");

foo.then(function(val) {
  console.log("second " + val);
});

// result
// first bar
// second bar


推荐答案

只需将它们保存在闭包内。

Simply save them inside of a closure.

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 ... 给你的消费者。

This is actually the majority of the difference between the "deferred" concept and the "promise" concept; one more level, on top, that has the actual remote-controls that you can give to someone else, while you hand the .then|.success|.done|etc... to your consumers.

一旦你把这些功能带到你的上游过程中,你可以愉快地懒得加载任何你喜欢的东西,使用thenable你将返回,然后随意成功或失败你的链(或让它挂起)...

Once you bring those functions out into your upstream process, you can happily lazy-load whatever you'd like, using the "thenable" which you'll return, and then succeed or fail your chain (or leave it hanging) at will...

看来这可能会继续成为选择的答案,并继续被拒绝,作为他所遇到的确切问题的解决方案(即:改造代码,而不是用ES6承诺) ,我想我会添加一个更详细的例子,说明为什么有选择地使用这个反模式可能比没有更好:

Seeing as this is probably going to continue to be the chosen answer, and continue to be voted down, as the solution to the exact problem he was having (ie: retrofitting code which was not made with ES6 promises in mind), I figure I'll add a more detailed example of exactly why using this antipattern selectively can be better than naught:

MongoClient.connect("mongodb://localhost:21017/mydb", (err, db) => {
    db.collection("mycollection", (err, collection) => {
        collection.find().toArray((err, results) => {
            doStuff(results);
        });
    });
});

如果我要写一个库,在这里,希望能达到我能写的地步:

If I were to write a library, here, hoping to reach the point where I could write:

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(查询,集合)
返回新的承诺(解决,拒绝){
/ *整个函数体,这里 /
/
做了许多与mongo.db.collection.find的解析无关的东西,但与它的调用* /
collection.find(query).toArray(/ )相关node-callback /(错误,结果){
if(err){
reject(err);
} else {
resolve(result);
}
});
};

...for ease of use within the library, does it make sense to wrap every single function-body within an instantiated promise // find = curry(query, collection) return new Promise(resolve, reject) { /* whole function body, here / / do lots of stuff which is irrelevant to the resolution of mongo.db.collection.find, but is relevant to its calling */ collection.find(query).toArray( /node-callback/(err, result) { if (err) { reject(err); } else { resolve(result); } }); };

...或者在查看真正只需要解析特定于节点的回调的模式时,是否更有意义某种形式的承诺解决方案,以节省必须写出/复制粘贴六个纯冗余线路,这些线路应该完全干掉?

...or in looking at the pattern of really only requiring the node-specific callback to be resolved, does it make more sense to have some form of promise-resolver, to save having to write out / copy-paste a half-dozen purely-redundant lines which should be completely DRYed up?

// find = curry(query, collection)
let resolver = new NodeResolver();
collection.find(query).toArray(promise.resolve);
return resolver.promise;

是的,这是一种反模式......但是,反模式需要的更少击键,恢复承诺链的自然流程,修复Node的回调专用API的问题,减少出错的可能性等等。

Yes, that is an anti-pattern... ...yet, an antipattern which requires fewer keystrokes, restores the natural flow of the promise-chain, fixes a problem with Node's callback-only API, reduces the potential for errors, et cetera.

是的,有已经执行此操作的库...
...特定于X库或Y的解决方案...
...或全局覆盖各种模块方法的解决方案(可怕)
.. 。或解决方案,再次,基本上迫使你传递你正在进行的电话的所有细节:

Yes, there are already libraries which do this... ...solutions specific to X library or Y... ...or solutions which globally override methods of various modules (scary) ...or solutions which, again, basically force you to pass in all of the details of the call you're making:

wrapNodeMethod(fs, "read", url, config).then(data => { /*...*/ });

但是没有简单的解决方案可以解决所有这些痛苦,没有:

But there is no simple solution for the case of inverting all of that pain, without either:

a)将整个函数体包装在一个promise中,使用库中的反模式为一个解析器
b提供异步回调,以便传递Node回调a resolver,函数体的其余部分需要准确知道。

a) wrapping the entire function body in a promise, to feed the async callback a resolver b) using an antipattern within a library, in order to pass Node callbacks a resolver that the rest of the function-body needs to know precisely nothing about.

即使需要在解析器中转换数据,返回仍然更有意义一个转换的集合,在一个新的承诺中

Even if data needed to be transformed within the resolver, it would still make more sense to return a transformed set, in a new promise

let resolver = new NodeResolver();
somethingAsync(resolver.resolve);
return resolver.promise.then(transformData).then(logTransform);

...而不是封装整个身体,包括变换等,仅用于闭包范围参考,只是为了避免一个反模式,这显然违背了已成为一个非常突出的JS平台/范例。

...than to wrap the whole body, including transforms, etc, just for closure-scope reference, just for the sake of avoiding an "antipattern" which clearly goes against the grain of what has become a very prominent JS platform/paradigm.

现在,就个人而言,我如果IO || Node方法返回一个promise和/或一个流,以及作为平台的核心部分进行回调,那会更高兴...
......这不会发生......

Now, personally, I'd be happier if IO||Node methods returned a promise and/or a stream, as well as taking a callback, as a core part of the platform... ...that's not going to happen...

...但你不可能告诉我少写,并保持Node模块DRY,同时仍然使用ES6 Promises是一个反模式,没有提供给我因此,一个更有说服力的解决方案。

...but you can't possibly tell me that writing less, and keeping Node modules DRY, while still using ES6 Promises is an "antipattern", without providing me a more-eloquent solution, therefore.

如果你能为我提供一些我可以在任何 NodeJS回调中使用的东西,确实,为此提供了一个更有说服力的解决方案,这样我就不必在新构造函数中包含每个包含异步回调的方法的每个主体,或者使用clunky dispatch方法,或劫持整个模块以覆盖他们的全局功能...

If you can, indeed, provide me something that I can use in any NodeJS callback, which does, indeed, provide a more eloquent solution to this, such that I don't have to wrap every body of every method which contains an async callback in a new constructor, or use clunky dispatcher methods, or hijack entire modules to override their global functionality...

...我非常愿意收回我的声明,即这个特定模式仍然存在非常有用,关于与容易出现金字塔的API的接口。

...I'd be more than willing to retract my statement that this particular pattern is still highly-useful, as regards interfacing with APIs which are prone to pyramids o'dewm.

这篇关于使用Javascript本机承诺,在附加了thenables之后解决承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆