链接多个异步函数
Chaining multiple asynchronous functions
简介
我有一个问题来自这个:
循环调用异步函数
有一次,我得到了一个循环,它使用类似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
问题
很明显,我不理解承诺的模式。我在两个API中读了很多:
- jsdeferred
- FF附加sdk
第一个是我一直用到现在的那个。第二个在我尝试要求库时出现错误:
const { defer } = require('api-utils/promise'); (+)
因此,我的问题是,您是否知道任何关于promise的好教程或一些关于链接多个异步函数的好例子。或者,如果你知道怎么做,你会怎么做。
谢谢
编辑:给出行(+)的错误
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'
Hm,看起来有点像范围界定问题。在上一个函数中,应该没有可用的变量resp
——我不确定它到底记录了什么。
是的,因为你最后再次调用asyncFunction
,只要响应中有一个id,你可能会得到一个无休止的循环。
然而,让我们尝试使用插件sdk的承诺(不,我以前从未使用过它们,但它说它是基于CommonJS承诺/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对象
- 调用后不异步Ajax忽略函数
- javascript函数中的异步与同步.(Node.js)
- Meteor:异步函数回调异常:onAfterAction
- 从框架中的函数异步加载 Javascript
- 为什么在定义回调/侦听器函数(异步消息传递,port.on)后没有立即设置全局变量
- 将javascript变量传输到插件函数(异步URL)
- 如何从 JavaScript 调用 JQuery 函数(异步调用后)
- 与其他变换函数异步制作不透明度动画
- 两个异步模块函数异步工作
- durandal激活函数异步代码
- 无法使我的示例函数异步
- 当内部函数异步执行某些操作时,如何从外部函数的回调返回值
- Javascript -使函数异步
- 如何使这个同步递归函数异步
- Promise.then()但函数异步运行
- 使用setimeout使命名函数异步化
- Javascript esriRequest (dojo)在函数异步问题
- 返回嵌套函数(异步)
- 我如何使这个JS函数异步