Promise 在这种情况下如何执行?
Posted
技术标签:
【中文标题】Promise 在这种情况下如何执行?【英文标题】:Promise how to implement in this situation? 【发布时间】:2016-07-27 15:26:14 【问题描述】:我在使用 fs.readfile 进行同步时遇到问题,它们第一次没有初始化,如果我再次尝试请求,那么我有结果。我知道我可以使用 Promise,并且我发现 Q from Kriskowal 有一些有用的东西。 我试过但没有成功。我不太了解如何实现它。如果有人可以帮助解决这个问题,我将永远感激不尽。
代码:
"use strict"
var Q = require('q');
var fs = require('fs');
var arrayZipBand = [];
var jsonZipCode = [];
var arrayParsedZipcodeBr = [];
exports.parse = function(opts)
if (opts.zipBand.constructor != Array)
opts.zipBand = [opts.zipBand];
if (opts.location.constructor != Array)
opts.location = [opts.location];
if (opts.config === 0)
opts.zipBand.forEach(function(file)
fs.readFile(file, 'utf8', function(err, logData)
if (err) throw err;
let text = logData.toString();
decodeURIComponent(text);
let lines = text.split('\n');
lines.forEach(function(line)
let parts = line.split('@');
if (parts[1] != undefined)
let obJson =
LOC_NU: parts[0],
LOC_CEP_INI: parts[1],
LOC_CEP_FIM: parts[2]
arrayZipBand.push(obJson);
);
);
);
opts.location.forEach(function(file)
fs.readFile(file, 'utf8', function(err, logData)
if (err) throw err;
let text = logData.toString();
decodeURIComponent(text);
let lines = text.split('\n');
lines.forEach(function(line)
let parts = line.split('@');
if (parts[1] != undefined)
for (let i = 0; i < arrayZipBand.length; i++)
if (parts[0] == arrayZipBand[i].LOC_NU)
jsonZipCode.push(arrayZipBand[i]);
if (jsonZipCode === undefined)
throw "Was not possible to find Zipcode for the id " + parts[0];
for (let i = 0; i < jsonZipCode.length; i++)
let obJson =
LOC_NU: parts[0],
UFE_SG: parts[1],
LOC_NO: parts[2],
MUN_NU: parts[8],
LOC_CEP_INI: jsonZipCode[i].LOC_CEP_INI,
LOC_CEP_FIM: jsonZipCode[i].LOC_CEP_FIM
arrayParsedZipcodeBr.push(obJson);
jsonZipCode = [];
);
);
);
;
return arrayParsedZipcodeBr;
【问题讨论】:
npmjs.com/package/promise-denodeify 那么,您是如何尝试使用 Promise 的?请edit您的问题向我们展示您的尝试。你读过 Q 文档吗?您是否看到使用Q
辅助函数调用 fs
方法以便从它们那里获得承诺的示例?
【参考方案1】:
嗯,您似乎正在尝试在循环周期中读取文件,但是以异步方式。第一个问题,为什么要异步读取这些文件?您可以随时同步阅读它们:
var data=fs.readFileSync(fname, encoding);
顺便说一句,如果您希望异步读取它们并保持 for...循环,您需要类似 Promise、定时等待或更复杂的同步机制。
您可以保持简单,而无需以这种方式使用任何其他包/模块:
/**
* Promise.All
* @param items Array of objects
* @param block Function block(item,index,resolve,reject)
* @param done Function Success block
* @param fail Function Failure block
* @example
promiseAll(["a","b","c"],
function(item,index,resolve,reject)
MyApp.call(item,function(result)
resolve(result);
,
function( error ) reject(error); ):
,
function(result) // aggregated results
,function(error) // error
)
* @author Loreto Parisi (loretoparisi at gmail dot com)
*/
promiseAll: function(items, block, done, fail)
var self = this;
var promises = [],
index = 0;
items.forEach(function(item)
promises.push(function(item, i)
return new Promise(function(resolve, reject)
if (block)
block.apply(this, [item, index, resolve, reject]);
);
(item, ++index))
);
Promise.all(promises).then(function AcceptHandler(results)
if (done) done(results);
, function ErrorHandler(error)
if (fail) fail(error);
);
, //promiseAll
所以你可以这样称呼它
promiseAll(arrayOfItems, function(item, index, resolve, reject)
// do something on item
if (someSuccessCondOnThisItem)
resolve(item)
else
reject(new Error("operation failed"))
, function(results) // aggregated results
console.log("All done %d", results.length);
, function(error) // error
console.log(error.toString());
);
请记住,这是一种非常简单的方法,但在大多数情况下,它在循环遍历数组时有效。
这是操场上的一个简单的工作示例:
var console =
log : function(s) document.getElementById("console").innerhtml+=s+"<br/>"
var promiseAll= function(items, block, done, fail)
var self = this;
var promises = [],
index = 0;
items.forEach(function(item)
promises.push(function(item, i)
return new Promise(function(resolve, reject)
if (block)
block.apply(this, [item, index, resolve, reject]);
);
(item, ++index))
);
Promise.all(promises).then(function AcceptHandler(results)
if (done) done(results);
, function ErrorHandler(error)
if (fail) fail(error);
);
; //promiseAll
arr=[1,2,3]
promiseAll(arr
,function(item,index,resolve,reject)
console.log("Resolving item[" + index+"]")
var okCond=true
if(okCond) resolve(item) else reject(new Error("item[" + index+"]"))
,function(results) // aggregated results
console.log("All done of "+results.length);
,function(error) // error
console.log(error);
);
<div id="console"/>
最后,一个完整的异步示例,展示了在循环遍历列表时如何延迟 XMLHttpRequest 的执行。 ExecutionBlock
在 SimpleRequest 响应后调用 reject
和 resolve
,导致 Promise 在调用 then
之前等待其执行。
var console =
log: function(s)
document.getElementById("console").innerHTML += s + "<br/>"
// Simple XMLHttpRequest
// based on https://davidwalsh.name/xmlhttprequest
SimpleRequest =
call: function(what, response)
var request;
if (window.XMLHttpRequest) // Mozilla, Safari, ...
request = new XMLHttpRequest();
else if (window.ActiveXObject) // IE
try
request = new ActiveXObject('Msxml2.XMLHTTP');
catch (e)
try
request = new ActiveXObject('Microsoft.XMLHTTP');
catch (e)
// state changes
request.onreadystatechange = function()
if (request.readyState === 4) // done
if (request.status === 200) // complete
response(request.responseText)
else response();
request.open('GET', what, true);
request.send(null);
//PromiseAll
var promiseAll = function(items, block, done, fail)
var self = this;
var promises = [],
index = 0;
items.forEach(function(item)
promises.push(function(item, i)
return new Promise(function(resolve, reject)
if (block)
block.apply(this, [item, index, resolve, reject]);
);
(item, ++index))
);
Promise.all(promises).then(function AcceptHandler(results)
if (done) done(results);
, function ErrorHandler(error)
if (fail) fail(error);
);
; //promiseAll
// LP: deferred execution block
var ExecutionBlock = function(item, index, resolve, reject)
SimpleRequest.call('https://icanhazip.com/', function(result)
if (result)
console.log("Response[" + index + "] " + result);
resolve(result);
else
reject(new Error("call error"));
)
arr = [1, 2, 3]
promiseAll(arr, function(item, index, resolve, reject)
console.log("Making request [" + index + "]")
ExecutionBlock(item, index, resolve, reject);
, function(results) // aggregated results
console.log("All response received " + results.length);
console.log(JSON.stringify(results));
, function(error) // error
console.log(error);
);
<div id="console" />
【讨论】:
@michelpm1 不客气,也许你可以编辑标题,比如promise all in for循环等。最后一个例子,展示了如何将数组作为XMLHttpRequest
减少到web网站网址...以上是关于Promise 在这种情况下如何执行?的主要内容,如果未能解决你的问题,请参考以下文章
promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解