Javascript承诺中的动态链接

Javascript承诺中的动态链接,javascript,promise,Javascript,Promise,如何在Javascript Promises中执行动态链接,我一直只看到调用的硬编码,例如,(promise).then(request/functionName).then(request/functionName)自从Promises展开以来,只需继续添加然后语句,它将继续链接在一起 function asyncSeries(fns) { return fns.reduce(function(p, fn) { return p.then(fn); }, Promise.res

如何在Javascript Promises中执行动态链接,我一直只看到调用的硬编码,例如,
(promise).then(request/functionName).then(request/functionName)

自从Promises展开以来,只需继续添加
然后
语句,它将继续链接在一起

function asyncSeries(fns) {
  return fns.reduce(function(p, fn) {
    return p.then(fn);
  }, Promise.resolve());
}
递归也是一种非常酷的方法:)


一种选择是利用对象的属性以及通过字符串调用它们的能力

我写了一个小样本,贴在下面

其思想是,您拥有希望在某个命名空间或对象中运行的函数集,就像我在“myNamespace”中所做的那样:

myNamespace = {
    "A": function() {return "A Function";},
    "B": function() {return "B Function";},
    "C": function() {return "C Function";}
}
然后,您的主要承诺将运行,并且以某种方式(通过输入、ajax、提示等)您将获得要运行的函数的字符串值,直到运行时才知道:

My main promise使用提示从用户处获取信函:

var answer = prompt('Starting.  Please pick a letter: A,B,C');
        if(myNamespace[answer] === undefined)
        {
            alert("Invalid choice!");
            reject("Invalid choice of: " + answer);
        }
        else
        {
            resolve(answer);
        }
在下一个“then”中,我使用该值(通过resolve函数传递)调用函数:

.then(function(response) {
        funcToRun = myNamespace[response]();})
最后,我将动态函数调用的结果输出到html,并使用一些递归的乐趣使其更具交互性,并证明它是动态的:

.then(function(){
        document.getElementById('result').innerHTML = funcToRun;})
    .then(function(){
        if(prompt("Run Again? (YES/NO)")==="YES")
        {
            doWork();
        }
    });
myNamespace={
“A”:function(){return“A function”;},
“B”:函数(){返回“B函数”;},
“C”:函数(){返回“C函数”;}
}
函数doWork()
{
var函子;
新承诺(功能(解决、拒绝){
var answer=prompt('开始。请选择一个字母:a、B、C');
if(myNamespace[answer]==未定义)
{
警告(“无效选择!”);
拒绝(“无效选择:“+答案”);
}
其他的
{
决心(回答);
}
})
.然后(功能(响应){
funcToRun=myNamespace[response]();})
.然后(函数(){
document.getElementById('result')。innerHTML=funcToRun;})
.然后(函数(){
如果(提示(“再次运行?(是/否)”)=“是”)
{
销钉();
}
});
}
销钉()

给定所有返回承诺的数组函数,您可以使用
reduce()
按顺序运行它们:

var myAsyncFuncs = [
    function (val) {return Promise.resolve(val + 1);},
    function (val) {return Promise.resolve(val + 2);},
    function (val) {return Promise.resolve(val + 3);},
];

myAsyncFuncs.reduce(function (prev, curr) {
    return prev.then(curr);
}, Promise.resolve(1))
.then(function (result) {
    console.log('RESULT is ' + result);  // prints "RESULT is 7"
});
上面的示例使用了promise库,但所有promise库都具有类似的功能

另外,创建承诺返回函数数组通常是使用
map()
的好选择。例如:

myNewOrmModels.map(function (model) {
    return model.save.bind(model);
}).reduce(function (prev, curr) {
    return prev.then(curr);
}, Promise.resolve())
.then(function (result) {
    console.log('DONE saving');
});

此解决方案基于EcmaScript 6()中引入的使用承诺,因此在使用前请参阅表浏览器的支持

代码

var f1 = function(){
    for (var i = 0; i < 800000000; i++) {}
    console.log('Function1 is done');
}
var f2 = function(){
    for (var i = 0; i < 800000000; i++) {}
    console.log('Function2 is done');
}
var f3 = function(){
    for (var i = 0; i < 800000000; i++) {}
    console.log('Function3 is done');
}
var f4 = function(){
    for (var i = 0; i < 800000000; i++) {}
    console.log('Function4 is done');
}


callbacks = function(){

    // copy passed arguments
    var callbacks = arguments;

    // create array functions
    var callbacks = Object.keys(callbacks).map(function(el){ return callbacks[el] });

    var now = Date.now();

    callbacks.reduce(function(previousPromise, currentFunc){
        return previousPromise.then(
            function(){
                currentFunc();
                var seconds = (Date.now() - now) / 1000;
                console.log('Gone', seconds, 'seconds');
            }
        )
    }, Promise.resolve());
}

callbacks(f1, f2, f3, f4);
注:

  • 如果函数包含计时器(针对此问题),则不起作用 我还尝试了jQuery的$Callbacks、$.Ajax和$.When,但没有帮助。 我发现,唯一的决定是在 计时器,但如果已完成功能,则不可接受。)
  • 测试环境

  • 这是ES7方式

    假设在一个数组中定义了多个承诺

      var funcs = [
        _ => new Promise(res => setTimeout(_ => res("1"), 1000)),
        _ => new Promise(res => setTimeout(_ => res("2"), 1000))
      }
    
    你想这样打电话

     chainPromises(funcs).then(result => console.log(result));
    
    为此,您可以使用
    async
    wait

      async function chainPromises(promises) {
        for (let promise of promises) {  // must be for (.. of ..)
          await promise();
        }
      }
    
    这将按顺序(逐个)执行给定的函数,而不是并行执行。参数
    Promise
    是一个函数数组,返回
    Promise


    Plunker:

    我的api提供程序遇到了一个问题,执行Promise.all()会导致并发数据库出现问题

    我的情况是,我需要得到每一个承诺结果,以显示一些“一切正常”或“某些错误”警报

    我不知道为什么。。这段代码在承诺解决问题时使用reduce,但我无法让我的范围工作(现在调查太迟了)

    所以多亏了这篇文章,我才带着这个小混蛋来到这里。。它没有抛光,但很好用

    $scope.recurse = function(promises, promisesLength, results) {
    
        if (promisesLength === 1) {
            return promises[0].then(function(data){
                results.push(data);
                return results;
            });
        }
    
        return promises[promisesLength-1].then(function(data) {
            results.push(data);
            return $scope.recurse(promises, promisesLength - 1, results);
        });
    
    }
    
    然后我像这样调用函数:

    var recurseFunction = $scope.recurse(promises, promises.length, results);
    recurseFunction.then(function (response) { ... });
    

    我希望它能有所帮助。

    查看以下教程以了解更多信息

  • javascript/node.js承诺的编程(动态)链接和
  • 使用递归函数的承诺链

  • 我认为最简单的方法是:

    const executePromises = function(listOfProviders){
    
        const p = Promise.resolve(null);
    
        for(let i = 0; i < listOfProviders.length; i++){
           p = p.then(v => listOfProviders[i]());
        }
    
       return p;
    
    };
    
    const executePromises=函数(listOfProviders){
    const p=Promise.resolve(null);
    for(设i=0;ilistOfProviders[i]());
    }
    返回p;
    };
    
    我相信以上基本上等同于:

    const executePromises = async function(listOfProviders) {
    
        for(let i = 0; i < listOfProviders.length; i++){
           await listOfProviders[i]();
        }
    
    };
    
    const executePromises=异步函数(listOfProviders){
    for(设i=0;i
    Dynamic-它们来自哪里?你想解决的问题是什么?当然,您可以传递任何您喜欢的回调,无论选择何种方式,而不仅仅是硬编码的函数表达式。感谢Bergi的回复,它们来自用户操作/事件,如按钮单击等,您的意思是像
    var promise=…;button.onclick=函数(e){promise.then(doSomething);}?你当然能做到,是的。你试过了吗?是的,用同样的方法…我没有主意了Bergi…那么你想要得到什么结果呢?您是否已经有了不起作用或看起来太复杂的代码?谢谢Jason。。。我将尝试实现相同的功能,并让您知道Hi Jason…快速问题…我将从用户操作中收到许多请求(要调用的FN),我如何检查当前承诺状态,然后链接它是否仍处于挂起状态,或者如果状态为resolved@RamuAjay因此,有一个承诺状态值,但它是私有的。我的猜测是使用
    .done(function(){isPromiseDone=true;})
    或某个外部变量来保存当前承诺状态。至于添加额外的“thens”,您可以保留一个函数数组,在
    .done()
    函数中,您可以检查该数组并在promise中添加更多的“thens”。。。不过这只是一个猜测。嗨,特拉维斯……快速提问……我将收到来自用户操作的许多请求(要调用的FN),呵呵
    $scope.recurse = function(promises, promisesLength, results) {
    
        if (promisesLength === 1) {
            return promises[0].then(function(data){
                results.push(data);
                return results;
            });
        }
    
        return promises[promisesLength-1].then(function(data) {
            results.push(data);
            return $scope.recurse(promises, promisesLength - 1, results);
        });
    
    }
    
    var recurseFunction = $scope.recurse(promises, promises.length, results);
    recurseFunction.then(function (response) { ... });
    
    const executePromises = function(listOfProviders){
    
        const p = Promise.resolve(null);
    
        for(let i = 0; i < listOfProviders.length; i++){
           p = p.then(v => listOfProviders[i]());
        }
    
       return p;
    
    };
    
    const executePromises = async function(listOfProviders) {
    
        for(let i = 0; i < listOfProviders.length; i++){
           await listOfProviders[i]();
        }
    
    };