javascript - 链接多个异步函数

标签 javascript firefox-addon firefox-addon-sdk promise

简介

我有一个问题来自这个:

Loop calling an asynchronous function

一旦我得到一个使用类似 promise 的模式调用异步函数的循环(使用 SDK 开发的附加组件中的 jsdeferred 库)。

var sess = ...;
Deferred.define(this);      
function asyncFunction (session) {
    Deferred.next(function() {
        var d = new Deferred();
        (new Request({
              url: form.php,
              content: "sess=" + session,
              onComplete: function (response) {
                  d.call(response.json);
              }
        })).get();
        return d;
    }).next(function(resp) {
        if (resp.id) {
            asyncFunction(session);
            console.log(resp.msg);              
        }           
    });
}

asyncFunction(sess);

我想将一个新的异步函数链接到此请求中,例如,打开浏览器的选项卡:我不想在准备就绪之前继续执行。

问题

所以我明白了:

var sess = ...;
Deferred.define(this);      
function asyncFunction (session) {
    Deferred.next(function() {
        var d = new Deferred();
        (new Request({
              url: form.php,
              content: "sess=" + session,
              onComplete: function (response) {
                  d.call(response.json);
              }
        })).get();
        return d;
    })
    .next(function(resp) {
        var d = new Deferred();
        // Load tab
        tabs.activeTab.url = 'http://foo.com';
        tabs.activeTab.on('ready', function() {
            console.log(resp.id);
            d.call(resp.id); 
        });
        return d;
    })
    .next(function(resp) {
        if (resp.id) {
            asyncFunction(session);
            console.log(resp.msg);              
        }           
    });
}

asyncFunction(sess);

我得到的结果是,对于循环的每次迭代,它都会再次运行之前的所有请求!所以我在我的控制台中得到了以下日志:

id1
msg1
id1
msg1
id2
msg2
id1
msg1
id2
msg2
id3
msg3
...

显然我的预期是:

id1
msg1
id2
msg2
id3
msg3

问题

很明显我不理解 promises 模式。我在两个 API 中阅读了很多内容:

第一个是我一直在使用的那个。当我尝试要求库时,第二个出现错误:

const { defer } = require('api-utils/promise'); (+)

所以,我的问题是,您是否知道关于 链接多个异步函数 的任何好的 promises 教程或一些好的示例。或者,如果您知道该怎么做,您会怎么做。

谢谢

编辑:给出行 (+) 的错误

error: An exception occurred.
Traceback (most recent call last):
  File "resource://ares-at-iiia-dot-csic/api-utils/lib/promise.js", line 16, in 
    }.call(this, function(require, exports) {
  File "resource://ares-at-iiia-dot-csic/api-utils/lib/promise.js", line 6, in return     function promised
    if (typeof(define) === 'function') { // RequireJS
  File "function promisedConcat(promises, unknown) {return promises.then(function         (values) {return resolve(unknown).then(function (valu
e) {return values.concat(value);});});", line NaN, in function promisedConcat
  File "function execute(args) {return call.apply(call, args);", line NaN, in function     execute
  File "exports.reject = reject;var promised = function () {var call =     Function.call;var concat = Array.prototype.concat", line NaN, in
 exports.reject = reject;var promised = function 
  File "function reject(reason, prototype) {var deferred =         defer(prototype);deferred.reject(reason);return deferred.promise;", line NaN
, in function reject
  File "exports.resolve = resolve", line NaN, in exports.resolve = resolve
  File "function resolve(value, prototype) {var deferred =     defer(prototype);deferred.resolve(value);return deferred.promise;", line NaN
, in function resolve
  File "exports.defer = defer", line NaN, in exports.defer = defer
  File "if (pending) {pending.push([resolved, rejected]);} else {result.then(resolved,     rejected);}return deferred.promise;}}});var defe
rred = {promise: promise, resolve: function resolve(value) {if (pending) {result =     isPromise(value) ? value : resolution(value);while (
pending.length) {result.then.apply(result, pending.shift());}pending = null;}},     reject", line NaN, in if 
  File "function rejected(reason) {deferred.resolve(reject(reason));", line NaN, in     function rejected
  File "function resolved(value) {deferred.resolve(resolve(value));", line NaN, in     function resolved
  File "function defer(prototype) {var pending = [], result;prototype = prototype ||     prototype === null ? prototype : Object.prototype;
var promise = Object.create(prototype, {then: {value: function then(resolve, reject)     {var deferred = defer(prototype);resolve = resolve
 ? attempt(resolve) : resolution;reject = reject ? attempt(reject) ", line NaN, in     function defer
  File "function isPromise(value) {return value && typeof value.then === "function";",     line NaN, in function isPromise
  File "function attempt(f) {return function effort(options) {try {return f(options);}     catch (error) {return rejection(error);}};", lin
e NaN, in function attempt
  File "function rejection(reason) {return {then", line NaN, in function rejection
  File "function resolution(value) {return {then", line NaN, in function resolution
  File "((function (require, exports) {"use strict"", line NaN, in 
  File "resource://ares-at-iiia-dot-csic/api-utils/lib/globals!.js", line 75, in getter
    value: define.bind(this)
TypeError: can't redefine non-configurable property 'define'

最佳答案

嗯,看起来有点像范围界定问题。在你的最后一个函数中,应该没有可用的变量 resp - 我不确定它真正记录了什么。

是的,因为你最后再次调用了 asyncFunction,只要响应中有一个 id,你就可能会陷入无限循环。

但是,让我们尝试使用 add-on sdk's promises (不,我以前从未使用过它们 - 但它说它基于 CommonJS Promises/A ):

const { defer } = require('api-utils/promise');
// or whatever you need in your code to use them - I'm no addOn-developer

var sess = ...;
Deferred.define(this);      
function asyncFunction (session) {
/* returns a promise itself */

    var d = defer();
    (new Request({
        url: form.php,
        content: "sess=" + session,
        onComplete: function (response) {
            d.resolve(response.json);
        }
    })).get();
    return d.promise.then(function(resp) {
        var d = defer();
        // Load tab
        tabs.activeTab.url = 'http://foo.com';
        tabs.activeTab.on('ready', function() {
            d.resolve(resp);
        });
        return d.promise;
    }).then(function(resp) {
        console.log("request #"+resp.id+"sucessful: "+resp.msg);  
        if (resp.id) {
            asyncFunction(session); // call recursively
        }           
    });
}
asyncFunction(sess);

关于javascript - 链接多个异步函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11450439/

相关文章:

javascript - 使用 Backbone.js 中的路由管理一页应用程序中的多个 View 实例

c# - 无效的回发或回调参数错误?

javascript - 如何为同一 jquery 对话框的不同实例调用不同的操作?

javascript - 如何从 firefox 浏览器中将选定的文本写为图像

javascript - 插件 SDK。我如何制作这样的弹出窗口?

firefox-addon - 如何让 TabBox 填满所有可用空间?

javascript - Addon SDK 获取 devtools 模块时出错

html - 如何向 Firefox 工具栏添加一个看起来合适的文本输入字段?

javascript - 聊天应用程序不会在 jquery 中每 10 秒加载一次

firefox-addon - 如何更改 Firefox 首选项(约 :config) using the new WebExtensions api?